blob: f42482b3fee607a5ac728f37595eafbf552660ad [file] [log] [blame]
Henrik Boström27c29362019-10-21 13:21:551/*
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 19:41:3622#if RTC_DCHECK_IS_ON
Henrik Boström27c29362019-10-21 13:21:5523 RTC_DCHECK(has_run_);
Tomas Gunnarsson36992362020-10-05 19:41:3624#endif
Henrik Boström27c29362019-10-21 13:21:5525}
26
27void OperationsChain::CallbackHandle::OnOperationComplete() {
Tomas Gunnarsson36992362020-10-05 19:41:3628#if RTC_DCHECK_IS_ON
Henrik Boström27c29362019-10-21 13:21:5529 RTC_DCHECK(!has_run_);
Henrik Boström27c29362019-10-21 13:21:5530 has_run_ = true;
31#endif // RTC_DCHECK_IS_ON
32 operations_chain_->OnOperationComplete();
Artem Titov96e3b992021-07-26 14:03:1433 // We have no reason to keep the `operations_chain_` alive through reference
Henrik Boström27c29362019-10-21 13:21:5534 // counting anymore.
35 operations_chain_ = nullptr;
36}
37
38// static
39scoped_refptr<OperationsChain> OperationsChain::Create() {
Niels Möller95129102022-01-13 10:00:0540 // Explicit new, to access private constructor.
41 return rtc::scoped_refptr<OperationsChain>(new OperationsChain());
Henrik Boström27c29362019-10-21 13:21:5542}
43
Niels Möller95129102022-01-13 10:00:0544OperationsChain::OperationsChain() {
Henrik Boström27c29362019-10-21 13:21:5545 RTC_DCHECK_RUN_ON(&sequence_checker_);
46}
47
48OperationsChain::~OperationsChain() {
49 // Operations keep the chain alive through reference counting so this should
50 // not be possible. The fact that the chain is empty makes it safe to
51 // destroy the OperationsChain on any sequence.
52 RTC_DCHECK(chained_operations_.empty());
53}
54
Henrik Boströme574a312020-08-25 08:20:1155void OperationsChain::SetOnChainEmptyCallback(
56 std::function<void()> on_chain_empty_callback) {
57 RTC_DCHECK_RUN_ON(&sequence_checker_);
58 on_chain_empty_callback_ = std::move(on_chain_empty_callback);
59}
60
61bool OperationsChain::IsEmpty() const {
62 RTC_DCHECK_RUN_ON(&sequence_checker_);
63 return chained_operations_.empty();
64}
65
Henrik Boström27c29362019-10-21 13:21:5566std::function<void()> OperationsChain::CreateOperationsChainCallback() {
Niels Möller95129102022-01-13 10:00:0567 return [handle = rtc::make_ref_counted<CallbackHandle>(
68 rtc::scoped_refptr<OperationsChain>(this))]() {
69 handle->OnOperationComplete();
70 };
Henrik Boström27c29362019-10-21 13:21:5571}
72
73void OperationsChain::OnOperationComplete() {
74 RTC_DCHECK_RUN_ON(&sequence_checker_);
75 // The front element is the operation that just completed, remove it.
76 RTC_DCHECK(!chained_operations_.empty());
77 chained_operations_.pop();
Henrik Boströme574a312020-08-25 08:20:1178 // If there are any other operations chained, execute the next one. Otherwise,
79 // invoke the "on chain empty" callback if it has been set.
Henrik Boström27c29362019-10-21 13:21:5580 if (!chained_operations_.empty()) {
81 chained_operations_.front()->Run();
Henrik Boströme574a312020-08-25 08:20:1182 } else if (on_chain_empty_callback_.has_value()) {
83 on_chain_empty_callback_.value()();
Henrik Boström27c29362019-10-21 13:21:5584 }
85}
86
87} // namespace rtc