blob: 11231a0b4445cdeb34c6415a44b6788b600afb89 [file] [log] [blame]
Danil Chapovalov348b08a2019-01-17 13:07:25 +01001/*
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#include "api/task_queue/task_queue_base.h"
11
12#include "absl/base/attributes.h"
Danil Chapovalov47cf5ea2019-02-19 20:20:16 +010013#include "absl/base/config.h"
Danil Chapovalov8feb6fd2022-07-05 11:01:27 +020014#include "absl/functional/any_invocable.h"
15#include "api/units/time_delta.h"
Danil Chapovalov47cf5ea2019-02-19 20:20:16 +010016#include "rtc_base/checks.h"
17
18#if defined(ABSL_HAVE_THREAD_LOCAL)
Danil Chapovalov348b08a2019-01-17 13:07:25 +010019
20namespace webrtc {
21namespace {
22
23ABSL_CONST_INIT thread_local TaskQueueBase* current = nullptr;
24
25} // namespace
26
27TaskQueueBase* TaskQueueBase::Current() {
28 return current;
29}
30
31TaskQueueBase::CurrentTaskQueueSetter::CurrentTaskQueueSetter(
32 TaskQueueBase* task_queue)
33 : previous_(current) {
34 current = task_queue;
35}
36
37TaskQueueBase::CurrentTaskQueueSetter::~CurrentTaskQueueSetter() {
38 current = previous_;
39}
Danil Chapovalov47cf5ea2019-02-19 20:20:16 +010040} // namespace webrtc
41
42#elif defined(WEBRTC_POSIX)
43
44#include <pthread.h>
45
46namespace webrtc {
47namespace {
48
49ABSL_CONST_INIT pthread_key_t g_queue_ptr_tls = 0;
50
51void InitializeTls() {
52 RTC_CHECK(pthread_key_create(&g_queue_ptr_tls, nullptr) == 0);
53}
54
55pthread_key_t GetQueuePtrTls() {
56 static pthread_once_t init_once = PTHREAD_ONCE_INIT;
57 RTC_CHECK(pthread_once(&init_once, &InitializeTls) == 0);
58 return g_queue_ptr_tls;
59}
60
61} // namespace
62
63TaskQueueBase* TaskQueueBase::Current() {
64 return static_cast<TaskQueueBase*>(pthread_getspecific(GetQueuePtrTls()));
65}
66
67TaskQueueBase::CurrentTaskQueueSetter::CurrentTaskQueueSetter(
68 TaskQueueBase* task_queue)
69 : previous_(TaskQueueBase::Current()) {
70 pthread_setspecific(GetQueuePtrTls(), task_queue);
71}
72
73TaskQueueBase::CurrentTaskQueueSetter::~CurrentTaskQueueSetter() {
74 pthread_setspecific(GetQueuePtrTls(), previous_);
75}
Danil Chapovalov348b08a2019-01-17 13:07:25 +010076
77} // namespace webrtc
Danil Chapovalov47cf5ea2019-02-19 20:20:16 +010078
79#else
80#error Unsupported platform
81#endif
Danil Chapovalov8feb6fd2022-07-05 11:01:27 +020082
83// Functions to support transition from std::unique_ptr<QueuedTask>
84// representation of a task to absl::AnyInvocable<void() &&> representation. In
85// the base interface older and newer functions call each other. This way
86// TaskQueue would work when classes derived from TaskQueueBase implements
87// either old set of Post functions (before the transition) or new set of Post
88// functions. Thus callers of the interface can be updated independently of all
89// of the implementations of that TaskQueueBase interface.
90
91// TODO(bugs.webrtc.org/14245): Delete these functions when transition is
92// complete.
93namespace webrtc {
94namespace {
95class Task : public QueuedTask {
96 public:
97 explicit Task(absl::AnyInvocable<void() &&> task) : task_(std::move(task)) {}
98 ~Task() override = default;
99
100 bool Run() override {
101 std::move(task_)();
102 return true;
103 }
104
105 private:
106 absl::AnyInvocable<void() &&> task_;
107};
108
109std::unique_ptr<QueuedTask> ToLegacy(absl::AnyInvocable<void() &&> task) {
110 return std::make_unique<Task>(std::move(task));
111}
112
113absl::AnyInvocable<void() &&> FromLegacy(std::unique_ptr<QueuedTask> task) {
114 return [task = std::move(task)]() mutable {
115 if (!task->Run()) {
116 task.release();
117 }
118 };
119}
120
121} // namespace
122
123void TaskQueueBase::PostTask(std::unique_ptr<QueuedTask> task) {
124 PostTask(FromLegacy(std::move(task)));
125}
126
127void TaskQueueBase::PostTask(absl::AnyInvocable<void() &&> task) {
128 PostTask(ToLegacy(std::move(task)));
129}
130
131void TaskQueueBase::PostDelayedTask(std::unique_ptr<QueuedTask> task,
132 uint32_t milliseconds) {
133 PostDelayedTask(FromLegacy(std::move(task)), TimeDelta::Millis(milliseconds));
134}
135
136void TaskQueueBase::PostDelayedTask(absl::AnyInvocable<void() &&> task,
137 TimeDelta delay) {
138 PostDelayedTask(ToLegacy(std::move(task)), delay.ms());
139}
140
141void TaskQueueBase::PostDelayedHighPrecisionTask(
142 absl::AnyInvocable<void() &&> task,
143 TimeDelta delay) {
144 PostDelayedHighPrecisionTask(ToLegacy(std::move(task)), delay.ms());
145}
146
147} // namespace webrtc