Lely core libraries  2.2.5
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 
37 namespace lely {
38 namespace ev {
39 
41 class 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
74  get_poll() const noexcept {
75  return Poll(ev_loop_get_poll(*this));
76  }
77 
79  Executor
80  get_executor() const noexcept {
81  return Executor(ev_loop_get_exec(*this));
82  }
83 
85  void
86  stop() noexcept {
87  ev_loop_stop(*this);
88  }
89 
91  bool
92  stopped() const noexcept {
93  return ev_loop_stopped(*this) != 0;
94  }
95 
97  void
98  restart() noexcept {
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
326  poll() {
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*
366  self() noexcept {
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_
::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 poll(::std::error_code &ec) noexcept
Definition: loop.hpp:335
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:217
A polling event loop.
Definition: loop.c:138
void ev_loop_destroy(ev_loop_t *loop)
Destroys a polling event loop.
Definition: loop.c:313
size_t ev_loop_wait_until(ev_loop_t *loop, ev_future_t *future, const struct timespec *abs_time)
Equivalent to size_t n = 0; while (ev_loop_wait_one_until(loop, future, abs_time)) n += n < S...
Definition: loop.c:392
::std::size_t run_one(::std::error_code &ec) noexcept
Definition: loop.hpp:281
size_t ev_loop_poll_one(ev_loop_t *loop)
Equivalent to ev_loop_run_one_until(loop, NULL).
Definition: loop.h:241
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:413
Poll get_poll() const noexcept
Definition: loop.hpp:74
size_t ev_loop_run_one(ev_loop_t *loop)
Equivalent to ev_loop_wait_one(loop, NULL).
Definition: loop.h:223
::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
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:330
::std::size_t poll_one(::std::error_code &ec) noexcept
Definition: loop.hpp:355
int ev_loop_kill(ev_loop_t *loop, void *thr)
Interrupts an event loop running on the specified thread.
Definition: loop.c:429
A future.
Definition: future.c:63
::std::size_t wait(ev_future_t *future)
Definition: loop.hpp:104
size_t ev_loop_wait(ev_loop_t *loop, ev_future_t *future)
Equivalent to size_t n = 0; while (ev_loop_wait_one(loop, future)) n += n < SIZE_MAX; return ...
Definition: loop.c:381
::std::size_t poll()
Definition: loop.hpp:326
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:957
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:404
::std::size_t wait_one(ev_future_t *future)
Definition: loop.hpp:160
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:229
This header file is part of the event library; it contains the polling event loop declarations...
::std::size_t wait_for(ev_future_t *future, const ::std::chrono::duration< Rep, Period > &d)
Definition: loop.hpp:125
void ev_loop_stop(ev_loop_t *loop)
Stops the event loop.
Definition: loop.c:338
::std::size_t run_one_until(const ::std::chrono::time_point< Clock, Duration > &t, ::std::error_code &ec) noexcept
Definition: loop.hpp:317
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:322
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
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function...
Definition: errnum.c:947
::std::size_t run(::std::error_code &ec) noexcept
Definition: loop.hpp:227
const struct ev_poll_vtbl *const ev_poll_t
The abstract polling interface.
Definition: poll.h:32
::std::size_t wait_until(ev_future_t *future, const ::std::chrono::time_point< Clock, Duration > &t)
Definition: loop.hpp:140
::std::size_t run_until(const ::std::chrono::time_point< Clock, Duration > &t)
Definition: loop.hpp:254
The abstract polling interface.
Definition: poll.hpp:36
::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
Loop(ev_poll_t *poll=nullptr, ::std::size_t npoll=1, bool poll_task=false)
Definition: loop.hpp:47
::std::size_t wait_one_until(ev_future_t *future, const ::std::chrono::time_point< Clock, Duration > &t)
Definition: loop.hpp:198
A polling event loop.
Definition: loop.hpp:41
::std::size_t wait(ev_future_t *future, ::std::error_code &ec) noexcept
Definition: loop.hpp:113
void * ev_loop_self(void)
Returns the identifier of the calling thread.
Definition: loop.c:423
int ev_loop_stopped(const ev_loop_t *loop)
Returns 1 if the event loop is stopped, and 0 if not.
Definition: loop.c:352
::std::size_t run_one_for(const ::std::chrono::duration< Rep, Period > &d)
Definition: loop.hpp:293
::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
::std::size_t run_for(const ::std::chrono::duration< Rep, Period > &d)
Definition: loop.hpp:239
This header file is part of the event library; it contains the C++ interface for the futures and prom...
::std::size_t run_until(const ::std::chrono::time_point< Clock, Duration > &t, ::std::error_code &ec) noexcept
Definition: loop.hpp:263
This header file is part of the event library; it contains the C++ interface for the abstract task ex...
errnum_t errc2num(int errc)
Transforms a native error code to a platform-independent error number.
Definition: errnum.c:310
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:286
bool stopped() const noexcept
@ see ev_loop_stopped()
Definition: loop.hpp:92
An abstract task executor. This class is a wrapper around ev_exec_t*.
Definition: exec.hpp:38
::std::error_code make_error_code(SdoErrc e) noexcept
Creates an error code corresponding to an SDO abort code.
Definition: sdo_error.cpp:170
::std::size_t wait_one(ev_future_t *future, ::std::error_code &ec) noexcept
Definition: loop.hpp:169
This header file is part of the utilities library; it contains the time function declarations.
This header file is part of the event library; it contains the C++ interface for the abstract polling...
::std::size_t run_for(const ::std::chrono::duration< Rep, Period > &d, ::std::error_code &ec) noexcept
Definition: loop.hpp:246
void kill(void *thr)
Definition: loop.hpp:372
::std::size_t poll_one()
Definition: loop.hpp:346
Definition: buf.hpp:32
void ev_loop_restart(ev_loop_t *loop)
Restarts an event loop.
Definition: loop.c:367
::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
::std::size_t wait_one_for(ev_future_t *future, const ::std::chrono::duration< Rep, Period > &d)
Definition: loop.hpp:181
::std::size_t run()
Definition: loop.hpp:218
size_t ev_loop_poll(ev_loop_t *loop)
Equivalent to ev_loop_run_until(loop, NULL).
Definition: loop.h:235
::std::size_t run_one()
Definition: loop.hpp:272
size_t ev_loop_run(ev_loop_t *loop)
Equivalent to ev_loop_wait(loop, NULL).
Definition: loop.h:211
Connection timed out.
Definition: errnum.h:226
Executor get_executor() const noexcept
Definition: loop.hpp:80
void restart() noexcept
Definition: loop.hpp:98