1 /*
2  *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "rtc_base/operations_chain.h"
12 
13 #include "rtc_base/checks.h"
14 
15 namespace rtc {
16 
CallbackHandle(scoped_refptr<OperationsChain> operations_chain)17 OperationsChain::CallbackHandle::CallbackHandle(
18     scoped_refptr<OperationsChain> operations_chain)
19     : operations_chain_(std::move(operations_chain)) {}
20 
~CallbackHandle()21 OperationsChain::CallbackHandle::~CallbackHandle() {
22   RTC_DCHECK(has_run_);
23 }
24 
OnOperationComplete()25 void OperationsChain::CallbackHandle::OnOperationComplete() {
26   RTC_DCHECK(!has_run_);
27 #ifdef RTC_DCHECK_IS_ON
28   has_run_ = true;
29 #endif  // RTC_DCHECK_IS_ON
30   operations_chain_->OnOperationComplete();
31   // We have no reason to keep the |operations_chain_| alive through reference
32   // counting anymore.
33   operations_chain_ = nullptr;
34 }
35 
36 // static
Create()37 scoped_refptr<OperationsChain> OperationsChain::Create() {
38   return new OperationsChain();
39 }
40 
OperationsChain()41 OperationsChain::OperationsChain() : RefCountedObject() {
42   RTC_DCHECK_RUN_ON(&sequence_checker_);
43 }
44 
~OperationsChain()45 OperationsChain::~OperationsChain() {
46   // Operations keep the chain alive through reference counting so this should
47   // not be possible. The fact that the chain is empty makes it safe to
48   // destroy the OperationsChain on any sequence.
49   RTC_DCHECK(chained_operations_.empty());
50 }
51 
CreateOperationsChainCallback()52 std::function<void()> OperationsChain::CreateOperationsChainCallback() {
53   return [handle = rtc::scoped_refptr<CallbackHandle>(
54               new CallbackHandle(this))]() { handle->OnOperationComplete(); };
55 }
56 
OnOperationComplete()57 void OperationsChain::OnOperationComplete() {
58   RTC_DCHECK_RUN_ON(&sequence_checker_);
59   // The front element is the operation that just completed, remove it.
60   RTC_DCHECK(!chained_operations_.empty());
61   chained_operations_.pop();
62   // If there are any other operations chained, execute the next one.
63   if (!chained_operations_.empty()) {
64     chained_operations_.front()->Run();
65   }
66 }
67 
68 }  // namespace rtc
69