1*d9f75844SAndroid Build Coastguard Worker /* 2*d9f75844SAndroid Build Coastguard Worker * Copyright 2019 The WebRTC Project Authors. All rights reserved. 3*d9f75844SAndroid Build Coastguard Worker * 4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license 5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source 6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found 7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may 8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree. 9*d9f75844SAndroid Build Coastguard Worker */ 10*d9f75844SAndroid Build Coastguard Worker 11*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/operations_chain.h" 12*d9f75844SAndroid Build Coastguard Worker 13*d9f75844SAndroid Build Coastguard Worker #include "api/make_ref_counted.h" 14*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h" 15*d9f75844SAndroid Build Coastguard Worker 16*d9f75844SAndroid Build Coastguard Worker namespace rtc { 17*d9f75844SAndroid Build Coastguard Worker CallbackHandle(scoped_refptr<OperationsChain> operations_chain)18*d9f75844SAndroid Build Coastguard WorkerOperationsChain::CallbackHandle::CallbackHandle( 19*d9f75844SAndroid Build Coastguard Worker scoped_refptr<OperationsChain> operations_chain) 20*d9f75844SAndroid Build Coastguard Worker : operations_chain_(std::move(operations_chain)) {} 21*d9f75844SAndroid Build Coastguard Worker ~CallbackHandle()22*d9f75844SAndroid Build Coastguard WorkerOperationsChain::CallbackHandle::~CallbackHandle() { 23*d9f75844SAndroid Build Coastguard Worker #if RTC_DCHECK_IS_ON 24*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(has_run_); 25*d9f75844SAndroid Build Coastguard Worker #endif 26*d9f75844SAndroid Build Coastguard Worker } 27*d9f75844SAndroid Build Coastguard Worker OnOperationComplete()28*d9f75844SAndroid Build Coastguard Workervoid OperationsChain::CallbackHandle::OnOperationComplete() { 29*d9f75844SAndroid Build Coastguard Worker #if RTC_DCHECK_IS_ON 30*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!has_run_); 31*d9f75844SAndroid Build Coastguard Worker has_run_ = true; 32*d9f75844SAndroid Build Coastguard Worker #endif // RTC_DCHECK_IS_ON 33*d9f75844SAndroid Build Coastguard Worker operations_chain_->OnOperationComplete(); 34*d9f75844SAndroid Build Coastguard Worker // We have no reason to keep the `operations_chain_` alive through reference 35*d9f75844SAndroid Build Coastguard Worker // counting anymore. 36*d9f75844SAndroid Build Coastguard Worker operations_chain_ = nullptr; 37*d9f75844SAndroid Build Coastguard Worker } 38*d9f75844SAndroid Build Coastguard Worker 39*d9f75844SAndroid Build Coastguard Worker // static Create()40*d9f75844SAndroid Build Coastguard Workerscoped_refptr<OperationsChain> OperationsChain::Create() { 41*d9f75844SAndroid Build Coastguard Worker // Explicit new, to access private constructor. 42*d9f75844SAndroid Build Coastguard Worker return rtc::scoped_refptr<OperationsChain>(new OperationsChain()); 43*d9f75844SAndroid Build Coastguard Worker } 44*d9f75844SAndroid Build Coastguard Worker OperationsChain()45*d9f75844SAndroid Build Coastguard WorkerOperationsChain::OperationsChain() { 46*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&sequence_checker_); 47*d9f75844SAndroid Build Coastguard Worker } 48*d9f75844SAndroid Build Coastguard Worker ~OperationsChain()49*d9f75844SAndroid Build Coastguard WorkerOperationsChain::~OperationsChain() { 50*d9f75844SAndroid Build Coastguard Worker // Operations keep the chain alive through reference counting so this should 51*d9f75844SAndroid Build Coastguard Worker // not be possible. The fact that the chain is empty makes it safe to 52*d9f75844SAndroid Build Coastguard Worker // destroy the OperationsChain on any sequence. 53*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(chained_operations_.empty()); 54*d9f75844SAndroid Build Coastguard Worker } 55*d9f75844SAndroid Build Coastguard Worker SetOnChainEmptyCallback(std::function<void ()> on_chain_empty_callback)56*d9f75844SAndroid Build Coastguard Workervoid OperationsChain::SetOnChainEmptyCallback( 57*d9f75844SAndroid Build Coastguard Worker std::function<void()> on_chain_empty_callback) { 58*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&sequence_checker_); 59*d9f75844SAndroid Build Coastguard Worker on_chain_empty_callback_ = std::move(on_chain_empty_callback); 60*d9f75844SAndroid Build Coastguard Worker } 61*d9f75844SAndroid Build Coastguard Worker IsEmpty() const62*d9f75844SAndroid Build Coastguard Workerbool OperationsChain::IsEmpty() const { 63*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&sequence_checker_); 64*d9f75844SAndroid Build Coastguard Worker return chained_operations_.empty(); 65*d9f75844SAndroid Build Coastguard Worker } 66*d9f75844SAndroid Build Coastguard Worker CreateOperationsChainCallback()67*d9f75844SAndroid Build Coastguard Workerstd::function<void()> OperationsChain::CreateOperationsChainCallback() { 68*d9f75844SAndroid Build Coastguard Worker return [handle = rtc::make_ref_counted<CallbackHandle>( 69*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<OperationsChain>(this))]() { 70*d9f75844SAndroid Build Coastguard Worker handle->OnOperationComplete(); 71*d9f75844SAndroid Build Coastguard Worker }; 72*d9f75844SAndroid Build Coastguard Worker } 73*d9f75844SAndroid Build Coastguard Worker OnOperationComplete()74*d9f75844SAndroid Build Coastguard Workervoid OperationsChain::OnOperationComplete() { 75*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&sequence_checker_); 76*d9f75844SAndroid Build Coastguard Worker // The front element is the operation that just completed, remove it. 77*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!chained_operations_.empty()); 78*d9f75844SAndroid Build Coastguard Worker chained_operations_.pop(); 79*d9f75844SAndroid Build Coastguard Worker // If there are any other operations chained, execute the next one. Otherwise, 80*d9f75844SAndroid Build Coastguard Worker // invoke the "on chain empty" callback if it has been set. 81*d9f75844SAndroid Build Coastguard Worker if (!chained_operations_.empty()) { 82*d9f75844SAndroid Build Coastguard Worker chained_operations_.front()->Run(); 83*d9f75844SAndroid Build Coastguard Worker } else if (on_chain_empty_callback_.has_value()) { 84*d9f75844SAndroid Build Coastguard Worker on_chain_empty_callback_.value()(); 85*d9f75844SAndroid Build Coastguard Worker } 86*d9f75844SAndroid Build Coastguard Worker } 87*d9f75844SAndroid Build Coastguard Worker 88*d9f75844SAndroid Build Coastguard Worker } // namespace rtc 89