Repository navigation
Expand file tree
/
Copy pathloop.hh
More file actions
197 lines (168 loc) · 5.61 KB
/
Copy pathloop.hh
File metadata and controls
197 lines (168 loc) · 5.61 KB
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#ifndef ORO_RUNTIME_LOOP_H
#define ORO_RUNTIME_LOOP_H
#include "platform.hh"
#include "options.hh"
namespace oro::runtime::loop {
using types::Atomic;
using types::Function;
using types::Mutex;
using types::Queue;
using types::Thread;
class Loop {
public:
using DispatchCallback = Function<void()>;
/**
* A container for libuv primatives.
*/
struct UV {
using RunMode = uv_run_mode;
uv_loop_t loop;
uv_async_t async;
Atomic<bool> isInitialized = false;
void open (Loop*);
void close ();
void stop ();
bool run (uv_run_mode = UV_RUN_DEFAULT);
int timeout () const;
int timeout ();
};
/**
* Various states the event loop will be in.
* even numbers are "final" states, odds are "pending"
*/
enum class State {
None = -1, // initial state, uninitialized, _should_ only transition out of this state
Init = 0, // loop is initialized, waiting to transition into new state
Idle = 1, // loop is idle, waiting for dispatch, this is a frequent state
Polling = 2, // loop is polling (dequeue) or currently executing (uv_run)
Paused = 3, // loop is paused - the loop is doing nothing
Stopped = 4, // loop is stopped and drained
Shutdown = 5 // loop is shutdown, it cannot be restored
};
/**
* Various options to configure the event loop
*/
struct Options : public oro::runtime::Options {
#if ORO_RUNTIME_PLATFORM_ANDROID || ORO_RUNTIME_PLATFORM_WINDOWS || ORO_RUNTIME_DESKTOP_EXTENSION
bool dedicatedThread = true;
#else
bool dedicatedThread = false;
#endif
};
#if ORO_RUNTIME_PLATFORM_LINUX
struct GTK {
GSource* source = nullptr;
GSourceFuncs functions {};
};
GTK gtk;
#endif
#if ORO_RUNTIME_PLATFORM_APPLE
dispatch_queue_t dispatchQueue = dispatch_queue_create(
"oro.runtime.core.loop.queue",
dispatch_queue_attr_make_with_qos_class(
DISPATCH_QUEUE_SERIAL,
QOS_CLASS_DEFAULT,
-1
)
);
#endif
const Options options;
const std::thread::id ownerThread = std::this_thread::get_id();
Queue<DispatchCallback> queue;
Thread thread;
Mutex mutex;
Atomic<State> state = State::None;
UV uv;
Loop ();
Loop (const Options&);
~Loop ();
Loop (const Loop&) = delete;
Loop (Loop&&) = delete;
Loop& operator = (const Loop&) = delete;
Loop& operator = (Loop&&) = delete;
/**
* Initializes loop if in a `None` state, transitioning it to a `Init`
* state. This function returns `true` such that
* `state >= Init && state < Shutdown` holds true.
*/
bool init ();
/**
* "Kicks" the loop to ensure it is active and running. Depending on the
* platform, the loop will be active on a dedicated thread, dispatch
* queue, or activated through a gsource function. This function will
* return `true` such that all state transitions are successful.
*/
bool kick ();
/**
* Start the loop if it isn't. This function will call `init()` and
* `kick()` such that all state transitions are successful.
*/
bool start ();
/**
* Stops the loop if it is active. This function will transition to a
* `Stopped` state and returns `true` if all state transitions are
* successful.
*/
bool stop ();
/**
* Resumes the loop if it was paused. This function will also start the
* loop if it hasn't been started yet. This function will result in a
* `Idle` or `Polling` state for the upon success and returns `true`
* if all state transitions are successful.
*/
bool resume ();
/**
* Pauses the loop if it is `Idle` or `Polling`. This function will return
* `false` if the loop is not in an "active" state such that
* `state > State::Init && state < State::Paused`.
*/
bool pause ();
/**
* Dispatches a callback asynchronously on the loop thread, starting an
* uninitialized loop when needed. A paused loop retains work until resume.
* Returns true when work is accepted; stopped/shutdown loops reject it.
*/
bool dispatch (const DispatchCallback&);
/**
* Returns true on the loop's dispatch queue, dedicated thread, or the
* creating thread of a loop driven by the platform event pump.
*/
bool isOnLoopThread () const;
/**
* Shuts down the loop, transitioning it into a state that cannot be
* transitioned out of.
*/
bool shutdown ();
/**
* Get a pointer to the underlying `uv_loop_t`.
*/
uv_loop_t* get ();
/**
* Returns `true` if the loop is "alive" (active handles and running)
*/
bool alive () const;
/**
* Returns `true` if the loop was "started" and its thread is active,
* if applicable.
*/
bool started () const;
/**
* Returns `true` if the loop was "stopped" (from a call to `stop()`)
*/
bool stopped () const;
/**
* Returns `true` if the loop was "paused" (from a call to `pause()`)
*/
bool paused () const;
/**
* Get the current loop backend timeout in milliseconds
*/
int timeout ();
int timeout () const;
/**
* Dispatch to the loop thread and cause it to sleep for `ms` milliseconds
*/
bool sleep (int64_t ms);
};
}
#endif