blob: 88d0b6fc714c611859a0b180eba6aab6abb234b2 [file] [log] [blame]
Karl Wiberg3d452cf2020-09-11 16:09:46 +02001/*
2 * Copyright 2020 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
Mirko Bonadei3d259352020-10-23 12:04:40 +020011#include "rtc_base/callback_list.h"
Karl Wiberg3d452cf2020-09-11 16:09:46 +020012
Karl Wiberg01a36f32020-11-11 11:48:04 +010013#include "rtc_base/checks.h"
14
Karl Wiberg3d452cf2020-09-11 16:09:46 +020015namespace webrtc {
Mirko Bonadei3d259352020-10-23 12:04:40 +020016namespace callback_list_impl {
Karl Wiberg3d452cf2020-09-11 16:09:46 +020017
Mirko Bonadei3d259352020-10-23 12:04:40 +020018CallbackListReceivers::CallbackListReceivers() = default;
Karl Wiberg01a36f32020-11-11 11:48:04 +010019
20CallbackListReceivers::~CallbackListReceivers() {
21 RTC_CHECK(!send_in_progress_);
22}
Karl Wiberg3d452cf2020-09-11 16:09:46 +020023
Karl Wiberg54b91412020-11-25 21:26:17 +010024void CallbackListReceivers::RemoveReceivers(const void* removal_tag) {
25 RTC_CHECK(!send_in_progress_);
26 RTC_DCHECK(removal_tag != nullptr);
27
28 // We divide the receivers_ vector into three regions: from right to left, the
29 // "keep" region, the "todo" region, and the "remove" region. The "todo"
30 // region initially covers the whole vector.
31 size_t first_todo = 0; // First element of the "todo"
32 // region.
33 size_t first_remove = receivers_.size(); // First element of the "remove"
34 // region.
35
36 // Loop until the "todo" region is empty.
37 while (first_todo != first_remove) {
38 if (receivers_[first_todo].removal_tag != removal_tag) {
39 // The first element of the "todo" region should be kept. Move the
40 // "keep"/"todo" boundary.
41 ++first_todo;
42 } else if (receivers_[first_remove - 1].removal_tag == removal_tag) {
43 // The last element of the "todo" region should be removed. Move the
44 // "todo"/"remove" boundary.
45 --first_remove;
46 } else {
47 // The first element of the "todo" region should be removed, and the last
48 // element of the "todo" region should be kept. Swap them, and then shrink
49 // the "todo" region from both ends.
50 RTC_DCHECK_NE(first_todo, first_remove - 1);
51 using std::swap;
52 swap(receivers_[first_todo], receivers_[first_remove - 1]);
53 RTC_DCHECK_NE(receivers_[first_todo].removal_tag, removal_tag);
54 ++first_todo;
55 RTC_DCHECK_EQ(receivers_[first_remove - 1].removal_tag, removal_tag);
56 --first_remove;
57 }
58 }
59
60 // Discard the remove region.
61 receivers_.resize(first_remove);
62}
63
Mirko Bonadei3d259352020-10-23 12:04:40 +020064void CallbackListReceivers::Foreach(
Karl Wiberg3d452cf2020-09-11 16:09:46 +020065 rtc::FunctionView<void(UntypedFunction&)> fv) {
Karl Wiberg01a36f32020-11-11 11:48:04 +010066 RTC_CHECK(!send_in_progress_);
67 send_in_progress_ = true;
Karl Wiberg3d452cf2020-09-11 16:09:46 +020068 for (auto& r : receivers_) {
Karl Wiberg54b91412020-11-25 21:26:17 +010069 fv(r.function);
Karl Wiberg3d452cf2020-09-11 16:09:46 +020070 }
Karl Wiberg01a36f32020-11-11 11:48:04 +010071 send_in_progress_ = false;
Karl Wiberg3d452cf2020-09-11 16:09:46 +020072}
73
Mirko Bonadei3d259352020-10-23 12:04:40 +020074template void CallbackListReceivers::AddReceiver(
Karl Wiberg54b91412020-11-25 21:26:17 +010075 const void*,
76 UntypedFunction::TrivialUntypedFunctionArgs<1>);
77template void CallbackListReceivers::AddReceiver(
78 const void*,
79 UntypedFunction::TrivialUntypedFunctionArgs<2>);
80template void CallbackListReceivers::AddReceiver(
81 const void*,
82 UntypedFunction::TrivialUntypedFunctionArgs<3>);
83template void CallbackListReceivers::AddReceiver(
84 const void*,
85 UntypedFunction::TrivialUntypedFunctionArgs<4>);
86template void CallbackListReceivers::AddReceiver(
87 const void*,
88 UntypedFunction::NontrivialUntypedFunctionArgs);
89template void CallbackListReceivers::AddReceiver(
90 const void*,
91 UntypedFunction::FunctionPointerUntypedFunctionArgs);
92
93template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +020094 UntypedFunction::TrivialUntypedFunctionArgs<1>);
Mirko Bonadei3d259352020-10-23 12:04:40 +020095template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +020096 UntypedFunction::TrivialUntypedFunctionArgs<2>);
Mirko Bonadei3d259352020-10-23 12:04:40 +020097template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +020098 UntypedFunction::TrivialUntypedFunctionArgs<3>);
Mirko Bonadei3d259352020-10-23 12:04:40 +020099template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +0200100 UntypedFunction::TrivialUntypedFunctionArgs<4>);
Mirko Bonadei3d259352020-10-23 12:04:40 +0200101template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +0200102 UntypedFunction::NontrivialUntypedFunctionArgs);
Mirko Bonadei3d259352020-10-23 12:04:40 +0200103template void CallbackListReceivers::AddReceiver(
Karl Wibergd2c69672020-09-29 13:55:13 +0200104 UntypedFunction::FunctionPointerUntypedFunctionArgs);
105
Mirko Bonadei3d259352020-10-23 12:04:40 +0200106} // namespace callback_list_impl
Karl Wiberg3d452cf2020-09-11 16:09:46 +0200107} // namespace webrtc