blob: 189b2373fbfd43287baf2f66ece3c52597e077bf [file] [log] [blame]
Henrik Boström27c29362019-10-21 15:21:55 +02001/*
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
15namespace rtc {
16
17OperationsChain::CallbackHandle::CallbackHandle(
18 scoped_refptr<OperationsChain> operations_chain)
19 : operations_chain_(std::move(operations_chain)) {}
20
21OperationsChain::CallbackHandle::~CallbackHandle() {
22 RTC_DCHECK(has_run_);
23}
24
25void 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
37scoped_refptr<OperationsChain> OperationsChain::Create() {
38 return new OperationsChain();
39}
40
41OperationsChain::OperationsChain() : RefCountedObject() {
42 RTC_DCHECK_RUN_ON(&sequence_checker_);
43}
44
45OperationsChain::~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
Henrik Boströme574a312020-08-25 10:20:11 +020052void OperationsChain::SetOnChainEmptyCallback(
53 std::function<void()> on_chain_empty_callback) {
54 RTC_DCHECK_RUN_ON(&sequence_checker_);
55 on_chain_empty_callback_ = std::move(on_chain_empty_callback);
56}
57
58bool OperationsChain::IsEmpty() const {
59 RTC_DCHECK_RUN_ON(&sequence_checker_);
60 return chained_operations_.empty();
61}
62
Henrik Boström27c29362019-10-21 15:21:55 +020063std::function<void()> OperationsChain::CreateOperationsChainCallback() {
64 return [handle = rtc::scoped_refptr<CallbackHandle>(
65 new CallbackHandle(this))]() { handle->OnOperationComplete(); };
66}
67
68void OperationsChain::OnOperationComplete() {
69 RTC_DCHECK_RUN_ON(&sequence_checker_);
70 // The front element is the operation that just completed, remove it.
71 RTC_DCHECK(!chained_operations_.empty());
72 chained_operations_.pop();
Henrik Boströme574a312020-08-25 10:20:11 +020073 // If there are any other operations chained, execute the next one. Otherwise,
74 // invoke the "on chain empty" callback if it has been set.
Henrik Boström27c29362019-10-21 15:21:55 +020075 if (!chained_operations_.empty()) {
76 chained_operations_.front()->Run();
Henrik Boströme574a312020-08-25 10:20:11 +020077 } else if (on_chain_empty_callback_.has_value()) {
78 on_chain_empty_callback_.value()();
Henrik Boström27c29362019-10-21 15:21:55 +020079 }
80}
81
82} // namespace rtc