xref: /aosp_15_r20/external/webrtc/rtc_base/operations_chain.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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)18 OperationsChain::CallbackHandle::CallbackHandle(
19     scoped_refptr<OperationsChain> operations_chain)
20     : operations_chain_(std::move(operations_chain)) {}
21 
~CallbackHandle()22 OperationsChain::CallbackHandle::~CallbackHandle() {
23 #if RTC_DCHECK_IS_ON
24   RTC_DCHECK(has_run_);
25 #endif
26 }
27 
OnOperationComplete()28 void 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()40 scoped_refptr<OperationsChain> OperationsChain::Create() {
41   // Explicit new, to access private constructor.
42   return rtc::scoped_refptr<OperationsChain>(new OperationsChain());
43 }
44 
OperationsChain()45 OperationsChain::OperationsChain() {
46   RTC_DCHECK_RUN_ON(&sequence_checker_);
47 }
48 
~OperationsChain()49 OperationsChain::~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)56 void 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() const62 bool OperationsChain::IsEmpty() const {
63   RTC_DCHECK_RUN_ON(&sequence_checker_);
64   return chained_operations_.empty();
65 }
66 
CreateOperationsChainCallback()67 std::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()74 void 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