1#pragma once
2
3#include <mbgl/actor/scheduler.hpp>
4#include <mbgl/actor/mailbox.hpp>
5#include <mbgl/util/noncopyable.hpp>
6#include <mbgl/util/util.hpp>
7#include <mbgl/util/work_task.hpp>
8#include <mbgl/util/work_request.hpp>
9
10#include <atomic>
11#include <functional>
12#include <utility>
13#include <queue>
14#include <mutex>
15
16namespace mbgl {
17namespace util {
18
19using LOOP_HANDLE = void *;
20
21class RunLoop : public Scheduler,
22 private util::noncopyable {
23public:
24 enum class Type : uint8_t {
25 Default,
26 New,
27 };
28
29 enum class Priority : bool {
30 Default = false,
31 High = true,
32 };
33
34 enum class Event : uint8_t {
35 None = 0,
36 Read = 1,
37 Write = 2,
38 ReadWrite = Read | Write,
39 };
40
41 RunLoop(Type type = Type::Default);
42 ~RunLoop() override;
43
44 static RunLoop* Get();
45 static LOOP_HANDLE getLoopHandle();
46
47 void run();
48 void runOnce();
49 void stop();
50
51 // So far only needed by the libcurl backend.
52 void addWatch(int fd, Event, std::function<void(int, Event)>&& callback);
53 void removeWatch(int fd);
54
55 // Invoke fn(args...) on this RunLoop.
56 template <class Fn, class... Args>
57 void invoke(Priority priority, Fn&& fn, Args&&... args) {
58 push(priority, task: WorkTask::make(std::forward<Fn>(fn), std::forward<Args>(args)...));
59 }
60
61 // Invoke fn(args...) on this RunLoop.
62 template <class Fn, class... Args>
63 void invoke(Fn&& fn, Args&&... args) {
64 invoke(Priority::Default, std::forward<Fn>(fn), std::forward<Args>(args)...);
65 }
66
67 // Post the cancellable work fn(args...) to this RunLoop.
68 template <class Fn, class... Args>
69 std::unique_ptr<AsyncRequest>
70 invokeCancellable(Fn&& fn, Args&&... args) {
71 std::shared_ptr<WorkTask> task = WorkTask::make(std::forward<Fn>(fn), std::forward<Args>(args)...);
72 push(priority: Priority::Default, task);
73 return std::make_unique<WorkRequest>(args&: task);
74 }
75
76 void schedule(std::weak_ptr<Mailbox> mailbox) override {
77 invoke(fn: [mailbox] () {
78 Mailbox::maybeReceive(mailbox);
79 });
80 }
81
82 class Impl;
83
84private:
85 MBGL_STORE_THREAD(tid)
86
87 using Queue = std::queue<std::shared_ptr<WorkTask>>;
88
89 // Wakes up the RunLoop so that it starts processing items in the queue.
90 void wake();
91
92 // Adds a WorkTask to the queue, and wakes it up.
93 void push(Priority priority, std::shared_ptr<WorkTask> task) {
94 std::lock_guard<std::mutex> lock(mutex);
95 if (priority == Priority::High) {
96 highPriorityQueue.emplace(args: std::move(task));
97 } else {
98 defaultQueue.emplace(args: std::move(task));
99 }
100 wake();
101 }
102
103 void process() {
104 std::shared_ptr<WorkTask> task;
105 std::unique_lock<std::mutex> lock(mutex);
106 while (true) {
107 if (!highPriorityQueue.empty()) {
108 task = std::move(highPriorityQueue.front());
109 highPriorityQueue.pop();
110 } else if (!defaultQueue.empty()) {
111 task = std::move(defaultQueue.front());
112 defaultQueue.pop();
113 } else {
114 break;
115 }
116 lock.unlock();
117 (*task)();
118 task.reset();
119 lock.lock();
120 }
121 }
122
123 Queue defaultQueue;
124 Queue highPriorityQueue;
125 std::mutex mutex;
126
127 std::unique_ptr<Impl> impl;
128};
129
130} // namespace util
131} // namespace mbgl
132
133#include <mbgl/util/work_task_impl.hpp>
134

source code of qtlocation/src/3rdparty/mapbox-gl-native/include/mbgl/util/run_loop.hpp