diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/libwebrtc/rtc_base/task_queue_gcd.cc | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/rtc_base/task_queue_gcd.cc')
-rw-r--r-- | third_party/libwebrtc/rtc_base/task_queue_gcd.cc | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/third_party/libwebrtc/rtc_base/task_queue_gcd.cc b/third_party/libwebrtc/rtc_base/task_queue_gcd.cc new file mode 100644 index 0000000000..6612b45f49 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/task_queue_gcd.cc @@ -0,0 +1,159 @@ +/* + * Copyright 2016 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. + */ + +// This file contains the implementation of TaskQueue for Mac and iOS. +// The implementation uses Grand Central Dispatch queues (GCD) to +// do the actual task queuing. + +#include "rtc_base/task_queue_gcd.h" + +#include <dispatch/dispatch.h> +#include <string.h> + +#include <memory> + +#include "absl/functional/any_invocable.h" +#include "absl/strings/string_view.h" +#include "api/task_queue/task_queue_base.h" +#include "api/units/time_delta.h" +#include "rtc_base/checks.h" +#include "rtc_base/logging.h" +#include "rtc_base/system/gcd_helpers.h" + +namespace webrtc { +namespace { + +int TaskQueuePriorityToGCD(TaskQueueFactory::Priority priority) { + switch (priority) { + case TaskQueueFactory::Priority::NORMAL: + return DISPATCH_QUEUE_PRIORITY_DEFAULT; + case TaskQueueFactory::Priority::HIGH: + return DISPATCH_QUEUE_PRIORITY_HIGH; + case TaskQueueFactory::Priority::LOW: + return DISPATCH_QUEUE_PRIORITY_LOW; + } +} + +class TaskQueueGcd final : public TaskQueueBase { + public: + TaskQueueGcd(absl::string_view queue_name, int gcd_priority); + + void Delete() override; + void PostTask(absl::AnyInvocable<void() &&> task) override; + void PostDelayedTask(absl::AnyInvocable<void() &&> task, + TimeDelta delay) override; + void PostDelayedHighPrecisionTask(absl::AnyInvocable<void() &&> task, + TimeDelta delay) override; + + private: + struct TaskContext { + TaskContext(TaskQueueGcd* queue, absl::AnyInvocable<void() &&> task) + : queue(queue), task(std::move(task)) {} + + TaskQueueGcd* const queue; + absl::AnyInvocable<void() &&> task; + }; + + ~TaskQueueGcd() override; + static void RunTask(void* task_context); + static void SetNotActive(void* task_queue); + static void DeleteQueue(void* task_queue); + + dispatch_queue_t queue_; + bool is_active_; +}; + +TaskQueueGcd::TaskQueueGcd(absl::string_view queue_name, int gcd_priority) + : queue_(RTCDispatchQueueCreateWithTarget( + std::string(queue_name).c_str(), + DISPATCH_QUEUE_SERIAL, + dispatch_get_global_queue(gcd_priority, 0))), + is_active_(true) { + RTC_CHECK(queue_); + dispatch_set_context(queue_, this); + // Assign a finalizer that will delete the queue when the last reference + // is released. This may run after the TaskQueue::Delete. + dispatch_set_finalizer_f(queue_, &DeleteQueue); +} + +TaskQueueGcd::~TaskQueueGcd() = default; + +void TaskQueueGcd::Delete() { + RTC_DCHECK(!IsCurrent()); + // Implementation/behavioral note: + // Dispatch queues are reference counted via calls to dispatch_retain and + // dispatch_release. Pending blocks submitted to a queue also hold a + // reference to the queue until they have finished. Once all references to a + // queue have been released, the queue will be deallocated by the system. + // This is why we check the is_active_ before running tasks. + + // Use dispatch_sync to set the is_active_ to guarantee that there's not a + // race with checking it from a task. + dispatch_sync_f(queue_, this, &SetNotActive); + dispatch_release(queue_); +} + +void TaskQueueGcd::PostTask(absl::AnyInvocable<void() &&> task) { + auto* context = new TaskContext(this, std::move(task)); + dispatch_async_f(queue_, context, &RunTask); +} + +void TaskQueueGcd::PostDelayedTask(absl::AnyInvocable<void() &&> task, + TimeDelta delay) { + auto* context = new TaskContext(this, std::move(task)); + dispatch_after_f(dispatch_time(DISPATCH_TIME_NOW, delay.us() * NSEC_PER_USEC), + queue_, context, &RunTask); +} + +void TaskQueueGcd::PostDelayedHighPrecisionTask( + absl::AnyInvocable<void() &&> task, + TimeDelta delay) { + PostDelayedTask(std::move(task), delay); +} + +// static +void TaskQueueGcd::RunTask(void* task_context) { + std::unique_ptr<TaskContext> tc(static_cast<TaskContext*>(task_context)); + CurrentTaskQueueSetter set_current(tc->queue); + if (tc->queue->is_active_) { + std::move(tc->task)(); + } + // Delete the task before CurrentTaskQueueSetter clears state that this code + // is running on the task queue. + tc = nullptr; +} + +// static +void TaskQueueGcd::SetNotActive(void* task_queue) { + static_cast<TaskQueueGcd*>(task_queue)->is_active_ = false; +} + +// static +void TaskQueueGcd::DeleteQueue(void* task_queue) { + delete static_cast<TaskQueueGcd*>(task_queue); +} + +class TaskQueueGcdFactory final : public TaskQueueFactory { + public: + std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue( + absl::string_view name, + Priority priority) const override { + return std::unique_ptr<TaskQueueBase, TaskQueueDeleter>( + new TaskQueueGcd(name, TaskQueuePriorityToGCD(priority))); + } +}; + +} // namespace + +std::unique_ptr<TaskQueueFactory> CreateTaskQueueGcdFactory() { + return std::make_unique<TaskQueueGcdFactory>(); +} + +} // namespace webrtc |