blob: f707d339b61cb3b8892cc792937f2154f3ad84ad [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() {
Tomas Gunnarsson36992362020-10-05 21:41:36 +020022#if RTC_DCHECK_IS_ON
Henrik Boström27c29362019-10-21 15:21:55 +020023 RTC_DCHECK(has_run_);
Tomas Gunnarsson36992362020-10-05 21:41:36 +020024#endif
Henrik Boström27c29362019-10-21 15:21:55 +020025}
26
27void OperationsChain::CallbackHandle::OnOperationComplete() {
Tomas Gunnarsson36992362020-10-05 21:41:36 +020028#if RTC_DCHECK_IS_ON
Henrik Boström27c29362019-10-21 15:21:55 +020029 RTC_DCHECK(!has_run_);
Henrik Boström27c29362019-10-21 15:21:55 +020030 has_run_ = true;
31#endif // RTC_DCHECK_IS_ON
32 operations_chain_->OnOperationComplete();
33 // We have no reason to keep the |operations_chain_| alive through reference
34 // counting anymore.
35 operations_chain_ = nullptr;
36}
37
38// static
39scoped_refptr<OperationsChain> OperationsChain::Create() {
40 return new OperationsChain();
41}
42
43OperationsChain::OperationsChain() : RefCountedObject() {
44 RTC_DCHECK_RUN_ON(&sequence_checker_);
45}
46
47OperationsChain::~OperationsChain() {
48 // Operations keep the chain alive through reference counting so this should
49 // not be possible. The fact that the chain is empty makes it safe to
50 // destroy the OperationsChain on any sequence.
51 RTC_DCHECK(chained_operations_.empty());
52}
53
Henrik Boströme574a312020-08-25 10:20:11 +020054void OperationsChain::SetOnChainEmptyCallback(
55 std::function<void()> on_chain_empty_callback) {
56 RTC_DCHECK_RUN_ON(&sequence_checker_);
57 on_chain_empty_callback_ = std::move(on_chain_empty_callback);
58}
59
60bool OperationsChain::IsEmpty() const {
61 RTC_DCHECK_RUN_ON(&sequence_checker_);
62 return chained_operations_.empty();
63}
64
Henrik Boström27c29362019-10-21 15:21:55 +020065std::function<void()> OperationsChain::CreateOperationsChainCallback() {
66 return [handle = rtc::scoped_refptr<CallbackHandle>(
67 new CallbackHandle(this))]() { handle->OnOperationComplete(); };
68}
69
70void OperationsChain::OnOperationComplete() {
71 RTC_DCHECK_RUN_ON(&sequence_checker_);
72 // The front element is the operation that just completed, remove it.
73 RTC_DCHECK(!chained_operations_.empty());
74 chained_operations_.pop();
Henrik Boströme574a312020-08-25 10:20:11 +020075 // If there are any other operations chained, execute the next one. Otherwise,
76 // invoke the "on chain empty" callback if it has been set.
Henrik Boström27c29362019-10-21 15:21:55 +020077 if (!chained_operations_.empty()) {
78 chained_operations_.front()->Run();
Henrik Boströme574a312020-08-25 10:20:11 +020079 } else if (on_chain_empty_callback_.has_value()) {
80 on_chain_empty_callback_.value()();
Henrik Boström27c29362019-10-21 15:21:55 +020081 }
82}
83
84} // namespace rtc