Lely core libraries 2.3.4
loop.hpp
Go to the documentation of this file.
1
24#ifndef LELY_EV_LOOP_HPP_
25#define LELY_EV_LOOP_HPP_
26
27#include <lely/ev/exec.hpp>
28#include <lely/ev/future.hpp>
29#include <lely/ev/loop.h>
30#include <lely/ev/poll.hpp>
31#include <lely/util/chrono.hpp>
32
33#include <cstddef>
34#include <type_traits>
35#include <utility>
36
37namespace lely {
38namespace ev {
39
41class Loop {
42 public:
44#if _WIN32
45 Loop(ev_poll_t* poll = nullptr, ::std::size_t npoll = 0,
46#else
47 Loop(ev_poll_t* poll = nullptr, ::std::size_t npoll = 1,
48#endif
49 bool poll_task = false)
50 : loop_(ev_loop_create(poll, npoll, poll_task)) {
51 if (!loop_) util::throw_errc("Loop");
52 }
53
54 Loop(const Loop&) = delete;
55
56 Loop(Loop&& other) noexcept : loop_(other.loop_) { other.loop_ = nullptr; }
57
58 Loop& operator=(const Loop&) = delete;
59
60 Loop&
61 operator=(Loop&& other) noexcept {
62 using ::std::swap;
63 swap(loop_, other.loop_);
64 return *this;
65 }
66
68 ~Loop() { ev_loop_destroy(*this); }
69
70 operator ev_loop_t*() const noexcept { return loop_; }
71
73 Poll
75 return Poll(ev_loop_get_poll(*this));
76 }
77
83
85 void
87 ev_loop_stop(*this);
88 }
89
91 bool
93 return ev_loop_stopped(*this) != 0;
94 }
95
97 void
99 ev_loop_restart(*this);
100 }
101
103 ::std::size_t
104 wait(ev_future_t* future) {
105 ::std::error_code ec;
106 auto result = wait(future, ec);
107 if (ec) throw ::std::system_error(ec, "wait");
108 return result;
109 }
110
112 ::std::size_t
113 wait(ev_future_t* future, ::std::error_code& ec) noexcept {
114 int errsv = get_errc();
115 set_errc(0);
116 auto result = ev_loop_wait(*this, future);
117 ec = util::make_error_code();
118 set_errc(errsv);
119 return result;
120 }
121
123 template <class Rep, class Period>
124 ::std::size_t
125 wait_for(ev_future_t* future, const ::std::chrono::duration<Rep, Period>& d) {
126 return wait_until(future, ::std::chrono::system_clock::now() + d);
127 }
128
130 template <class Rep, class Period>
131 ::std::size_t
132 wait_for(ev_future_t* future, const ::std::chrono::duration<Rep, Period>& d,
133 ::std::error_code& ec) noexcept {
134 return wait_until(future, ::std::chrono::system_clock::now() + d, ec);
135 }
136
138 template <class Clock, class Duration>
139 ::std::size_t
141 const ::std::chrono::time_point<Clock, Duration>& t) {
142 auto abs_time =
143 util::to_timespec(compat::clock_cast<::std::chrono::system_clock>(t));
144 return wait_until(future, &abs_time);
145 }
146
148 template <class Clock, class Duration>
149 ::std::size_t
151 const ::std::chrono::time_point<Clock, Duration>& t,
152 ::std::error_code& ec) noexcept {
153 auto abs_time =
154 util::to_timespec(compat::clock_cast<::std::chrono::system_clock>(t));
155 return wait_until(future, &abs_time, ec);
156 }
157
159 ::std::size_t
161 ::std::error_code ec;
162 auto result = wait_one(future, ec);
163 if (ec) throw ::std::system_error(ec, "wait_one");
164 return result;
165 }
166
168 ::std::size_t
169 wait_one(ev_future_t* future, ::std::error_code& ec) noexcept {
170 int errsv = get_errc();
171 set_errc(0);
172 auto result = ev_loop_wait_one(*this, future);
173 ec = util::make_error_code();
174 set_errc(errsv);
175 return result;
176 }
177
179 template <class Rep, class Period>
180 ::std::size_t
182 const ::std::chrono::duration<Rep, Period>& d) {
183 return wait_one_until(future, ::std::chrono::system_clock::now() + d);
184 }
185
187 template <class Rep, class Period>
188 ::std::size_t
190 const ::std::chrono::duration<Rep, Period>& d,
191 ::std::error_code& ec) noexcept {
192 return wait_one_until(future, ::std::chrono::system_clock::now() + d, ec);
193 }
194
196 template <class Clock, class Duration>
197 ::std::size_t
199 const ::std::chrono::time_point<Clock, Duration>& t) {
200 auto abs_time =
201 util::to_timespec(compat::clock_cast<::std::chrono::system_clock>(t));
202 return wait_one_until(future, &abs_time);
203 }
204
206 template <class Clock, class Duration>
207 ::std::size_t
209 const ::std::chrono::time_point<Clock, Duration>& t,
210 ::std::error_code& ec) noexcept {
211 auto abs_time =
212 util::to_timespec(compat::clock_cast<::std::chrono::system_clock>(t));
213 return wait_one_until(future, &abs_time, ec);
214 }
215
217 ::std::size_t
218 run() {
219 ::std::error_code ec;
220 auto result = run(ec);
221 if (ec) throw ::std::system_error(ec, "run");
222 return result;
223 }
224
226 ::std::size_t
227 run(::std::error_code& ec) noexcept {
228 int errsv = get_errc();
229 set_errc(0);
230 auto result = ev_loop_run(*this);
231 ec = util::make_error_code();
232 set_errc(errsv);
233 return result;
234 }
235
237 template <class Rep, class Period>
238 ::std::size_t
239 run_for(const ::std::chrono::duration<Rep, Period>& d) {
240 return run_until(::std::chrono::system_clock::now() + d);
241 }
242
244 template <class Rep, class Period>
245 ::std::size_t
246 run_for(const ::std::chrono::duration<Rep, Period>& d,
247 ::std::error_code& ec) noexcept {
248 return run_until(::std::chrono::system_clock::now() + d, ec);
249 }
250
252 template <class Clock, class Duration>
253 ::std::size_t
254 run_until(const ::std::chrono::time_point<Clock, Duration>& t) {
255 auto abs_time =
256 util::to_timespec(compat::clock_cast<::std::chrono::system_clock>(t));
257 return run_until(&abs_time);
258 }
259
261 template <class Clock, class Duration>
262 ::std::size_t
263 run_until(const ::std::chrono::time_point<Clock, Duration>& t,
264 ::std::error_code& ec) noexcept {
265 auto abs_time =
266 util::to_timespec(compat::clock_cast<::std::chrono::system_clock>(t));
267 return run_until(&abs_time, ec);
268 }
269
271 ::std::size_t
273 ::std::error_code ec;
274 auto result = run_one(ec);
275 if (ec) throw ::std::system_error(ec, "run_one");
276 return result;
277 }
278
280 ::std::size_t
281 run_one(::std::error_code& ec) noexcept {
282 int errsv = get_errc();
283 set_errc(0);
284 auto result = ev_loop_run_one(*this);
285 ec = util::make_error_code();
286 set_errc(errsv);
287 return result;
288 }
289
291 template <class Rep, class Period>
292 ::std::size_t
293 run_one_for(const ::std::chrono::duration<Rep, Period>& d) {
294 return run_one_until(::std::chrono::system_clock::now() + d);
295 }
296
298 template <class Rep, class Period>
299 ::std::size_t
300 run_one_for(const ::std::chrono::duration<Rep, Period>& d,
301 ::std::error_code& ec) noexcept {
302 return run_one_until(::std::chrono::system_clock::now() + d, ec);
303 }
304
306 template <class Clock, class Duration>
307 ::std::size_t
308 run_one_until(const ::std::chrono::time_point<Clock, Duration>& t) {
309 auto abs_time =
310 util::to_timespec(compat::clock_cast<::std::chrono::system_clock>(t));
311 return run_one_until(&abs_time);
312 }
313
315 template <class Clock, class Duration>
316 ::std::size_t
317 run_one_until(const ::std::chrono::time_point<Clock, Duration>& t,
318 ::std::error_code& ec) noexcept {
319 auto abs_time =
320 util::to_timespec(compat::clock_cast<::std::chrono::system_clock>(t));
321 return run_one_until(&abs_time, ec);
322 }
323
325 ::std::size_t
327 ::std::error_code ec;
328 auto result = poll(ec);
329 if (ec) throw ::std::system_error(ec, "poll");
330 return result;
331 }
332
334 ::std::size_t
335 poll(::std::error_code& ec) noexcept {
336 int errsv = get_errc();
337 set_errc(0);
338 auto result = ev_loop_poll(*this);
339 ec = util::make_error_code();
340 set_errc(errsv);
341 return result;
342 }
343
345 ::std::size_t
347 ::std::error_code ec;
348 auto result = poll_one(ec);
349 if (ec) throw ::std::system_error(ec, "poll_one");
350 return result;
351 }
352
354 ::std::size_t
355 poll_one(::std::error_code& ec) noexcept {
356 int errsv = get_errc();
357 set_errc(0);
358 auto result = ev_loop_poll_one(*this);
359 ec = util::make_error_code();
360 set_errc(errsv);
361 return result;
362 }
363
365 static void*
367 return ev_loop_self();
368 }
369
371 void
372 kill(void* thr) {
373 if (ev_loop_kill(*this, thr) == -1) util::throw_errc("kill");
374 }
375
376 protected:
377 ::std::size_t
378 wait_until(ev_future_t* future, const timespec* abs_time) {
379 ::std::error_code ec;
380 auto result = wait_until(future, abs_time, ec);
381 if (ec && errc2num(ec.value()) != ERRNUM_TIMEDOUT)
382 throw ::std::system_error(ec, "wait_until");
383 return result;
384 }
385
386 ::std::size_t
387 wait_until(ev_future_t* future, const timespec* abs_time,
388 ::std::error_code& ec) noexcept {
389 int errsv = get_errc();
390 set_errc(0);
391 auto result = ev_loop_wait_until(*this, future, abs_time);
392 ec = util::make_error_code();
393 set_errc(errsv);
394 return result;
395 }
396
397 ::std::size_t
398 wait_one_until(ev_future_t* future, const timespec* abs_time) {
399 ::std::error_code ec;
400 auto result = wait_one_until(future, abs_time, ec);
401 if (ec && errc2num(ec.value()) != ERRNUM_TIMEDOUT)
402 throw ::std::system_error(ec, "wait_one_until");
403 return result;
404 }
405
406 ::std::size_t
407 wait_one_until(ev_future_t* future, const timespec* abs_time,
408 ::std::error_code& ec) noexcept {
409 int errsv = get_errc();
410 set_errc(0);
411 auto result = ev_loop_wait_one_until(*this, future, abs_time);
412 ec = util::make_error_code();
413 set_errc(errsv);
414 return result;
415 }
416
417 ::std::size_t
418 run_until(const timespec* abs_time) {
419 ::std::error_code ec;
420 auto result = run_until(abs_time, ec);
421 if (ec && errc2num(ec.value()) != ERRNUM_TIMEDOUT)
422 throw ::std::system_error(ec, "run_until");
423 return result;
424 }
425
426 ::std::size_t
427 run_until(const timespec* abs_time, ::std::error_code& ec) noexcept {
428 int errsv = get_errc();
429 set_errc(0);
430 auto result = ev_loop_run_until(*this, abs_time);
431 ec = util::make_error_code();
432 set_errc(errsv);
433 return result;
434 }
435
436 ::std::size_t
437 run_one_until(const timespec* abs_time) {
438 ::std::error_code ec;
439 auto result = run_one_until(abs_time, ec);
440 if (ec && errc2num(ec.value()) != ERRNUM_TIMEDOUT)
441 throw ::std::system_error(ec, "run_one_until");
442 return result;
443 }
444
445 ::std::size_t
446 run_one_until(const timespec* abs_time, ::std::error_code& ec) noexcept {
447 int errsv = get_errc();
448 set_errc(0);
449 auto result = ev_loop_run_one_until(*this, abs_time);
450 ec = util::make_error_code();
451 set_errc(errsv);
452 return result;
453 }
454
455 private:
456 ev_loop_t* loop_{nullptr};
457};
458
459} // namespace ev
460} // namespace lely
461
462#endif // !LELY_EV_LOOP_HPP_
A CANopen value.
Definition val.hpp:42
An abstract task executor. This class is a wrapper around #ev_exec_t*.
Definition exec.hpp:38
A polling event loop.
Definition loop.hpp:41
::std::size_t wait_one_for(ev_future_t *future, const ::std::chrono::duration< Rep, Period > &d)
Definition loop.hpp:181
Executor get_executor() const noexcept
Definition loop.hpp:80
::std::size_t run_one_until(const ::std::chrono::time_point< Clock, Duration > &t, ::std::error_code &ec) noexcept
Definition loop.hpp:317
Poll get_poll() const noexcept
Definition loop.hpp:74
::std::size_t poll_one()
Definition loop.hpp:346
::std::size_t wait_one_for(ev_future_t *future, const ::std::chrono::duration< Rep, Period > &d, ::std::error_code &ec) noexcept
Definition loop.hpp:189
::std::size_t wait_one_until(ev_future_t *future, const ::std::chrono::time_point< Clock, Duration > &t, ::std::error_code &ec) noexcept
Definition loop.hpp:208
::std::size_t wait_one_until(ev_future_t *future, const ::std::chrono::time_point< Clock, Duration > &t)
Definition loop.hpp:198
::std::size_t poll(::std::error_code &ec) noexcept
Definition loop.hpp:335
::std::size_t wait_one(ev_future_t *future, ::std::error_code &ec) noexcept
Definition loop.hpp:169
::std::size_t run_until(const ::std::chrono::time_point< Clock, Duration > &t, ::std::error_code &ec) noexcept
Definition loop.hpp:263
::std::size_t run_for(const ::std::chrono::duration< Rep, Period > &d)
Definition loop.hpp:239
::std::size_t poll_one(::std::error_code &ec) noexcept
Definition loop.hpp:355
void kill(void *thr)
Definition loop.hpp:372
::std::size_t run_one_for(const ::std::chrono::duration< Rep, Period > &d)
Definition loop.hpp:293
::std::size_t run_one()
Definition loop.hpp:272
::std::size_t run(::std::error_code &ec) noexcept
Definition loop.hpp:227
::std::size_t run()
Definition loop.hpp:218
void stop() noexcept
Definition loop.hpp:86
::std::size_t run_one_until(const ::std::chrono::time_point< Clock, Duration > &t)
Definition loop.hpp:308
void restart() noexcept
Definition loop.hpp:98
bool stopped() const noexcept
@ see ev_loop_stopped()
Definition loop.hpp:92
::std::size_t wait(ev_future_t *future)
Definition loop.hpp:104
::std::size_t run_one(::std::error_code &ec) noexcept
Definition loop.hpp:281
::std::size_t run_until(const ::std::chrono::time_point< Clock, Duration > &t)
Definition loop.hpp:254
::std::size_t wait(ev_future_t *future, ::std::error_code &ec) noexcept
Definition loop.hpp:113
::std::size_t run_one_for(const ::std::chrono::duration< Rep, Period > &d, ::std::error_code &ec) noexcept
Definition loop.hpp:300
::std::size_t wait_for(ev_future_t *future, const ::std::chrono::duration< Rep, Period > &d)
Definition loop.hpp:125
::std::size_t wait_until(ev_future_t *future, const ::std::chrono::time_point< Clock, Duration > &t, ::std::error_code &ec) noexcept
Definition loop.hpp:150
static void * self() noexcept
Definition loop.hpp:366
Loop(ev_poll_t *poll=nullptr, ::std::size_t npoll=1, bool poll_task=false)
Definition loop.hpp:47
::std::size_t wait_until(ev_future_t *future, const ::std::chrono::time_point< Clock, Duration > &t)
Definition loop.hpp:140
::std::size_t wait_one(ev_future_t *future)
Definition loop.hpp:160
::std::size_t poll()
Definition loop.hpp:326
::std::size_t run_for(const ::std::chrono::duration< Rep, Period > &d, ::std::error_code &ec) noexcept
Definition loop.hpp:246
::std::size_t wait_for(ev_future_t *future, const ::std::chrono::duration< Rep, Period > &d, ::std::error_code &ec) noexcept
Definition loop.hpp:132
The abstract polling interface.
Definition poll.hpp:36
errnum_t errc2num(int errc)
Transforms a native error code to a platform-independent error number.
Definition errnum.c:309
@ ERRNUM_TIMEDOUT
Connection timed out.
Definition errnum.h:229
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition errnum.c:932
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition errnum.c:944
const struct ev_poll_vtbl *const ev_poll_t
The abstract polling interface.
Definition poll.h:32
This header file is part of the event library; it contains the C++ interface for the abstract polling...
This header file is part of the event library; it contains the C++ interface for the abstract task ex...
This header file is part of the event library; it contains the C++ interface for the futures and prom...
This header file is part of the event library; it contains the polling event loop declarations.
ev_loop_t * ev_loop_create(ev_poll_t *poll, size_t npoll, int poll_task)
Creates a new polling event loop.
Definition loop.c:291
size_t ev_loop_run_one(ev_loop_t *loop)
Equivalent to ev_loop_wait_one(loop, NULL).
Definition loop.h:227
int ev_loop_kill(ev_loop_t *loop, void *thr)
Interrupts an event loop running on the specified thread.
Definition loop.c:434
size_t ev_loop_wait_one(ev_loop_t *loop, ev_future_t *future)
If the event loop has pending tasks, runs a single task.
Definition loop.c:409
void ev_loop_destroy(ev_loop_t *loop)
Destroys a polling event loop.
Definition loop.c:318
void * ev_loop_self(void)
Returns the identifier of the calling thread.
Definition loop.c:428
size_t ev_loop_poll(ev_loop_t *loop)
Equivalent to ev_loop_run_until(loop, NULL).
Definition loop.h:239
size_t ev_loop_poll_one(ev_loop_t *loop)
Equivalent to ev_loop_run_one_until(loop, NULL).
Definition loop.h:245
size_t ev_loop_run_until(ev_loop_t *loop, const struct timespec *abs_time)
Equivalent to ev_loop_wait_until(loop, NULL, abs_time).
Definition loop.h:221
ev_poll_t * ev_loop_get_poll(const ev_loop_t *loop)
Returns a pointer to the polling instance used by the event loop, or NULL if the loop does not poll.
Definition loop.c:327
size_t ev_loop_run(ev_loop_t *loop)
Equivalent to ev_loop_wait(loop, NULL).
Definition loop.h:215
ev_exec_t * ev_loop_get_exec(const ev_loop_t *loop)
Returns a pointer to the executor corresponding to the event loop.
Definition loop.c:335
void ev_loop_stop(ev_loop_t *loop)
Stops the event loop.
Definition loop.c:343
size_t ev_loop_wait(ev_loop_t *loop, ev_future_t *future)
Equivalent to.
Definition loop.c:386
size_t ev_loop_wait_one_until(ev_loop_t *loop, ev_future_t *future, const struct timespec *abs_time)
If the event loop has pending tasks, runs a single task.
Definition loop.c:418
size_t ev_loop_wait_until(ev_loop_t *loop, ev_future_t *future, const struct timespec *abs_time)
Equivalent to.
Definition loop.c:397
size_t ev_loop_run_one_until(ev_loop_t *loop, const struct timespec *abs_time)
Equivalent to ev_loop_wait_one_until(loop, NULL, abs_time).
Definition loop.h:233
int ev_loop_stopped(const ev_loop_t *loop)
Returns 1 if the event loop is stopped, and 0 if not.
Definition loop.c:357
void ev_loop_restart(ev_loop_t *loop)
Restarts an event loop.
Definition loop.c:372
A future.
Definition future.c:66
A polling event loop.
Definition loop.c:141
A time type with nanosecond resolution.
Definition time.h:88
This header file is part of the utilities library; it contains the time function declarations.