summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/rtc_base/callback_list.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/libwebrtc/rtc_base/callback_list.cc
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/rtc_base/callback_list.cc')
-rw-r--r--third_party/libwebrtc/rtc_base/callback_list.cc121
1 files changed, 121 insertions, 0 deletions
diff --git a/third_party/libwebrtc/rtc_base/callback_list.cc b/third_party/libwebrtc/rtc_base/callback_list.cc
new file mode 100644
index 0000000000..c452c79b38
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/callback_list.cc
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2020 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/callback_list.h"
+
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+namespace callback_list_impl {
+
+CallbackListReceivers::CallbackListReceivers() = default;
+
+CallbackListReceivers::~CallbackListReceivers() {
+ RTC_CHECK(!send_in_progress_);
+}
+
+void CallbackListReceivers::RemoveReceivers(const void* removal_tag) {
+ RTC_DCHECK(removal_tag);
+
+ // We divide the receivers_ vector into three regions: from right to left, the
+ // "keep" region, the "todo" region, and the "remove" region. The "todo"
+ // region initially covers the whole vector.
+ size_t first_todo = 0; // First element of the "todo"
+ // region.
+ size_t first_remove = receivers_.size(); // First element of the "remove"
+ // region.
+
+ // Loop until the "todo" region is empty.
+ while (first_todo != first_remove) {
+ if (receivers_[first_todo].removal_tag != removal_tag) {
+ // The first element of the "todo" region should be kept. Move the
+ // "keep"/"todo" boundary.
+ ++first_todo;
+ } else if (receivers_[first_remove - 1].removal_tag == removal_tag) {
+ // The last element of the "todo" region should be removed. Move the
+ // "todo"/"remove" boundary.
+ if (send_in_progress_) {
+ // Tag this receiver for removal, which will be done when `ForEach`
+ // has completed.
+ receivers_[first_remove - 1].removal_tag = pending_removal_tag();
+ }
+ --first_remove;
+ } else if (!send_in_progress_) {
+ // The first element of the "todo" region should be removed, and the last
+ // element of the "todo" region should be kept. Swap them, and then shrink
+ // the "todo" region from both ends.
+ RTC_DCHECK_NE(first_todo, first_remove - 1);
+ using std::swap;
+ swap(receivers_[first_todo], receivers_[first_remove - 1]);
+ RTC_DCHECK_NE(receivers_[first_todo].removal_tag, removal_tag);
+ ++first_todo;
+ RTC_DCHECK_EQ(receivers_[first_remove - 1].removal_tag, removal_tag);
+ --first_remove;
+ }
+ }
+
+ if (!send_in_progress_) {
+ // Discard the remove region.
+ receivers_.resize(first_remove);
+ }
+}
+
+void CallbackListReceivers::Foreach(
+ rtc::FunctionView<void(UntypedFunction&)> fv) {
+ RTC_CHECK(!send_in_progress_);
+ bool removals_detected = false;
+ send_in_progress_ = true;
+ for (auto& r : receivers_) {
+ RTC_DCHECK_NE(r.removal_tag, pending_removal_tag());
+ fv(r.function);
+ if (r.removal_tag == pending_removal_tag()) {
+ removals_detected = true;
+ }
+ }
+ send_in_progress_ = false;
+ if (removals_detected) {
+ RemoveReceivers(pending_removal_tag());
+ }
+}
+
+template void CallbackListReceivers::AddReceiver(
+ const void*,
+ UntypedFunction::TrivialUntypedFunctionArgs<1>);
+template void CallbackListReceivers::AddReceiver(
+ const void*,
+ UntypedFunction::TrivialUntypedFunctionArgs<2>);
+template void CallbackListReceivers::AddReceiver(
+ const void*,
+ UntypedFunction::TrivialUntypedFunctionArgs<3>);
+template void CallbackListReceivers::AddReceiver(
+ const void*,
+ UntypedFunction::TrivialUntypedFunctionArgs<4>);
+template void CallbackListReceivers::AddReceiver(
+ const void*,
+ UntypedFunction::NontrivialUntypedFunctionArgs);
+template void CallbackListReceivers::AddReceiver(
+ const void*,
+ UntypedFunction::FunctionPointerUntypedFunctionArgs);
+
+template void CallbackListReceivers::AddReceiver(
+ UntypedFunction::TrivialUntypedFunctionArgs<1>);
+template void CallbackListReceivers::AddReceiver(
+ UntypedFunction::TrivialUntypedFunctionArgs<2>);
+template void CallbackListReceivers::AddReceiver(
+ UntypedFunction::TrivialUntypedFunctionArgs<3>);
+template void CallbackListReceivers::AddReceiver(
+ UntypedFunction::TrivialUntypedFunctionArgs<4>);
+template void CallbackListReceivers::AddReceiver(
+ UntypedFunction::NontrivialUntypedFunctionArgs);
+template void CallbackListReceivers::AddReceiver(
+ UntypedFunction::FunctionPointerUntypedFunctionArgs);
+
+} // namespace callback_list_impl
+} // namespace webrtc