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 "api/make_ref_counted.h" 14 #include "rtc_base/checks.h" 15 16 namespace rtc { 17 CallbackHandle(scoped_refptr<OperationsChain> operations_chain)18OperationsChain::CallbackHandle::CallbackHandle( 19 scoped_refptr<OperationsChain> operations_chain) 20 : operations_chain_(std::move(operations_chain)) {} 21 ~CallbackHandle()22OperationsChain::CallbackHandle::~CallbackHandle() { 23 #if RTC_DCHECK_IS_ON 24 RTC_DCHECK(has_run_); 25 #endif 26 } 27 OnOperationComplete()28void OperationsChain::CallbackHandle::OnOperationComplete() { 29 #if RTC_DCHECK_IS_ON 30 RTC_DCHECK(!has_run_); 31 has_run_ = true; 32 #endif // RTC_DCHECK_IS_ON 33 operations_chain_->OnOperationComplete(); 34 // We have no reason to keep the `operations_chain_` alive through reference 35 // counting anymore. 36 operations_chain_ = nullptr; 37 } 38 39 // static Create()40scoped_refptr<OperationsChain> OperationsChain::Create() { 41 // Explicit new, to access private constructor. 42 return rtc::scoped_refptr<OperationsChain>(new OperationsChain()); 43 } 44 OperationsChain()45OperationsChain::OperationsChain() { 46 RTC_DCHECK_RUN_ON(&sequence_checker_); 47 } 48 ~OperationsChain()49OperationsChain::~OperationsChain() { 50 // Operations keep the chain alive through reference counting so this should 51 // not be possible. The fact that the chain is empty makes it safe to 52 // destroy the OperationsChain on any sequence. 53 RTC_DCHECK(chained_operations_.empty()); 54 } 55 SetOnChainEmptyCallback(std::function<void ()> on_chain_empty_callback)56void OperationsChain::SetOnChainEmptyCallback( 57 std::function<void()> on_chain_empty_callback) { 58 RTC_DCHECK_RUN_ON(&sequence_checker_); 59 on_chain_empty_callback_ = std::move(on_chain_empty_callback); 60 } 61 IsEmpty() const62bool OperationsChain::IsEmpty() const { 63 RTC_DCHECK_RUN_ON(&sequence_checker_); 64 return chained_operations_.empty(); 65 } 66 CreateOperationsChainCallback()67std::function<void()> OperationsChain::CreateOperationsChainCallback() { 68 return [handle = rtc::make_ref_counted<CallbackHandle>( 69 rtc::scoped_refptr<OperationsChain>(this))]() { 70 handle->OnOperationComplete(); 71 }; 72 } 73 OnOperationComplete()74void OperationsChain::OnOperationComplete() { 75 RTC_DCHECK_RUN_ON(&sequence_checker_); 76 // The front element is the operation that just completed, remove it. 77 RTC_DCHECK(!chained_operations_.empty()); 78 chained_operations_.pop(); 79 // If there are any other operations chained, execute the next one. Otherwise, 80 // invoke the "on chain empty" callback if it has been set. 81 if (!chained_operations_.empty()) { 82 chained_operations_.front()->Run(); 83 } else if (on_chain_empty_callback_.has_value()) { 84 on_chain_empty_callback_.value()(); 85 } 86 } 87 88 } // namespace rtc 89