-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathtask_queue.h
112 lines (92 loc) · 3.75 KB
/
task_queue.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#pragma once
#include <stdint.h>
#include <memory>
#include <string_view>
#include "queued_task.h"
namespace vi {
// Implements a task queue that asynchronously executes tasks in a way that
// guarantees that they're executed in FIFO order and that tasks never overlap.
// Tasks may always execute on the same worker thread and they may not.
// To DCHECK that tasks are executing on a known task queue, use IsCurrent().
//
// Here are some usage examples:
//
// 1) Asynchronously running a lambda:
//
// class MyClass {
// ...
// TaskQueue queue_("MyQueue");
// };
//
// void MyClass::StartWork() {
// queue_.PostTask([]() { Work(); });
// ...
//
// 2) Posting a custom task on a timer. The task posts itself again after
// every running:
//
// class TimerTask : public QueuedTask {
// public:
// TimerTask() {}
// private:
// bool Run() override {
// ++count_;
// TaskQueueBase::Current()->PostDelayedTask(
// absl::WrapUnique(this), 1000);
// // Ownership has been transferred to the next occurance,
// // so return false to prevent from being deleted now.
// return false;
// }
// int count_ = 0;
// };
// ...
// queue_.PostDelayedTask(std::make_unique<TimerTask>(), 1000);
//
// For more examples, see task_queue_unittests.cc.
//
// A note on destruction:
//
class TaskQueueBase;
class TaskQueueDeleter;
// When a TaskQueue is deleted, pending tasks will not be executed but they will
// be deleted. The deletion of tasks may happen asynchronously after the
// TaskQueue itself has been deleted or it may happen synchronously while the
// TaskQueue instance is being deleted. This may vary from one OS to the next
// so assumptions about lifetimes of pending tasks should not be made.
class TaskQueue {
public:
explicit TaskQueue(std::unique_ptr<TaskQueueBase, TaskQueueDeleter> taskQueue);
~TaskQueue();
static std::unique_ptr<TaskQueue> create(std::string_view name);
// Used for DCHECKing the current queue.
bool isCurrent() const;
// Returns non-owning pointer to the task queue implementation.
TaskQueueBase* get() { return impl_; }
// TODO(tommi): For better debuggability, implement RTC_FROM_HERE.
// Ownership of the task is passed to PostTask.
void postTask(std::unique_ptr<QueuedTask> task);
// Schedules a task to execute a specified number of milliseconds from when
// the call is made. The precision should be considered as "best effort"
// and in some cases, such as on Windows when all high precision timers have
// been used up, can be off by as much as 15 millseconds (although 8 would be
// more likely). This can be mitigated by limiting the use of delayed tasks.
void postDelayedTask(std::unique_ptr<QueuedTask> task, uint32_t milliseconds);
// std::enable_if is used here to make sure that calls to PostTask() with
// std::unique_ptr<SomeClassDerivedFromQueuedTask> would not end up being
// caught by this template.
template <class Closure, typename std::enable_if<!std::is_convertible<Closure, std::unique_ptr<QueuedTask>>::value>::type* = nullptr>
void postTask(Closure&& closure) {
postTask(ToQueuedTask(std::forward<Closure>(closure)));
}
// See documentation above for performance expectations.
template <class Closure, typename std::enable_if<!std::is_convertible<Closure, std::unique_ptr<QueuedTask>>::value>::type* = nullptr>
void postDelayedTask(Closure&& closure, uint32_t milliseconds) {
postDelayedTask(ToQueuedTask(std::forward<Closure>(closure)), milliseconds);
}
private:
TaskQueue& operator=(const TaskQueue&) = delete;
TaskQueue(const TaskQueue&) = delete;
private:
TaskQueueBase* const impl_;
};
}