Lely core libraries  2.3.4
tqueue.hpp
Go to the documentation of this file.
1 
24 #ifndef LELY_IO2_TQUEUE_HPP_
25 #define LELY_IO2_TQUEUE_HPP_
26 
27 #include <lely/io2/timer.hpp>
28 #include <lely/io2/tqueue.h>
29 
30 #include <utility>
31 
32 namespace lely {
33 namespace io {
34 
35 namespace detail {
36 
37 template <class F>
39  public:
40  TimerQueueWaitWrapper(ev_exec_t* exec, F&& f)
42  0, 0, exec,
43  [](ev_task* task) noexcept {
44  auto wait = io_tqueue_wait_from_task(task);
45  ::std::error_code ec;
46  if (wait->errc) ec = util::make_error_code(wait->errc);
47  auto self = static_cast<TimerQueueWaitWrapper*>(wait);
48  compat::invoke(::std::move(self->func_), ec);
49  delete self;
50  }),
51  func_(::std::forward<F>(f)) {}
52 
54 
55  TimerQueueWaitWrapper& operator=(const TimerQueueWaitWrapper&) = delete;
56 
57  private:
58  typename ::std::decay<F>::type func_;
59 };
60 
61 } // namespace detail
62 
68 template <class F>
69 // clang-format off
70 inline typename ::std::enable_if<
74  // clang-format on
75  return new detail::TimerQueueWaitWrapper<F>(exec, ::std::forward<F>(f));
76 }
77 
84  public:
85  using Signature = void(::std::error_code);
86 
88  template <class F>
89  TimerQueueWait(ev_exec_t* exec, F&& f)
91  IO_TQUEUE_WAIT_INIT(0, 0, exec,
92  [](ev_task* task) noexcept {
93  auto wait = io_tqueue_wait_from_task(task);
94  auto self = static_cast<TimerQueueWait*>(wait);
95  if (self->func_) {
96  ::std::error_code ec;
97  if (wait->errc)
98  ec = util::make_error_code(wait->errc);
99  self->func_(ec);
100  }
101  }),
102  func_(::std::forward<F>(f)) {}
103 
105  template <class F>
106  explicit TimerQueueWait(F&& f)
107  : TimerQueueWait(nullptr, ::std::forward<F>(f)) {}
108 
109  TimerQueueWait(const TimerQueueWait&) = delete;
110 
111  TimerQueueWait& operator=(const TimerQueueWait&) = delete;
112 
113  operator ev_task&() & noexcept { return task; }
114 
117  get_executor() const noexcept {
118  return ev::Executor(task.exec);
119  }
120 
121  private:
122  ::std::function<Signature> func_;
123 };
124 
126 class TimerQueue : public Device {
127  public:
128  using Device::operator io_dev_t*;
129 
131  explicit TimerQueue(io_timer_t* timer, ev_exec_t* exec = nullptr)
132  : Device(nullptr), tq_(io_tqueue_create(timer, exec)) {
133  if (tq_)
134  dev = io_tqueue_get_dev(*this);
135  else
136  util::throw_errc("TimerQueue");
137  }
138 
139  TimerQueue(const TimerQueue&) = delete;
140 
141  TimerQueue(TimerQueue&& other) noexcept : Device(other.dev), tq_(other.tq_) {
142  other.tq_ = nullptr;
143  other.dev = nullptr;
144  }
145 
146  TimerQueue& operator=(const TimerQueue&) = delete;
147 
148  TimerQueue&
149  operator=(TimerQueue&& other) noexcept {
150  using ::std::swap;
151  swap(tq_, other.tq_);
152  swap(dev, other.dev);
153  return *this;
154  }
155 
158 
159  operator io_tqueue_t*() const noexcept { return tq_; }
160 
162  TimerBase
163  get_timer() const noexcept {
164  return TimerBase(io_tqueue_get_timer(*this));
165  }
166 
168  void
169  submit_wait(io_tqueue_wait& wait) noexcept {
170  io_tqueue_submit_wait(*this, &wait);
171  }
172 
174  void
175  submit_wait(const TimerBase::time_point& t, io_tqueue_wait& wait) noexcept {
176  wait.value = util::to_timespec(t);
177  submit_wait(wait);
178  }
179 
181  void
182  submit_wait(const TimerBase::duration& d, io_tqueue_wait& wait) {
183  auto now = get_timer().get_clock().gettime();
184  wait.value = util::to_timespec(now + d);
185  submit_wait(wait);
186  }
187 
189  template <class F>
190  void
191  submit_wait(const TimerBase::time_point& t, ev_exec_t* exec, F&& f) {
192  submit_wait(t, *make_timer_queue_wait_wrapper(exec, ::std::forward<F>(f)));
193  }
194 
196  template <class F>
197  void
198  submit_wait(const TimerBase::duration& d, ev_exec_t* exec, F&& f) {
199  submit_wait(d, *make_timer_queue_wait_wrapper(exec, ::std::forward<F>(f)));
200  }
201 
203  template <class F>
204  typename ::std::enable_if<!::std::is_base_of<
205  io_tqueue_wait, typename ::std::decay<F>::type>::value>::type
206  submit_wait(const TimerBase::time_point& t, F&& f) {
207  submit_wait(t, nullptr, ::std::forward<F>(f));
208  }
209 
211  template <class F>
212  typename ::std::enable_if<!::std::is_base_of<
213  io_tqueue_wait, typename ::std::decay<F>::type>::value>::type
214  submit_wait(const TimerBase::duration& d, F&& f) {
215  submit_wait(d, nullptr, ::std::forward<F>(f));
216  }
217 
219  bool
220  cancel_wait(struct io_tqueue_wait& wait) noexcept {
221  return io_tqueue_cancel_wait(*this, &wait) != 0;
222  }
223 
225  bool
226  abort_wait(struct io_tqueue_wait& wait) noexcept {
227  return io_tqueue_abort_wait(*this, &wait) != 0;
228  }
229 
232  async_wait(ev_exec_t* exec, const TimerBase::time_point& t,
233  struct io_tqueue_wait** pwait = nullptr) {
234  auto value = util::to_timespec(t);
235  auto future = io_tqueue_async_wait(*this, exec, &value, pwait);
236  if (!future) util::throw_errc("async_wait");
237  return ev::Future<void, int>(future);
238  }
239 
242  async_wait(const TimerBase::time_point& t,
243  struct io_tqueue_wait** pwait = nullptr) {
244  return async_wait(nullptr, t, pwait);
245  }
246 
249  async_wait(ev_exec_t* exec, const TimerBase::duration& d,
250  struct io_tqueue_wait** pwait = nullptr) {
251  auto now = get_timer().get_clock().gettime();
252  return async_wait(exec, now + d, pwait);
253  }
254 
257  async_wait(const TimerBase::duration& d,
258  struct io_tqueue_wait** pwait = nullptr) {
259  return async_wait(nullptr, d, pwait);
260  }
261 
262  private:
263  io_tqueue_t* tq_{nullptr};
264 };
265 
266 } // namespace io
267 } // namespace lely
268 
269 #endif // !LELY_IO2_TQUEUE_HPP_
An abstract task executor. This class is a wrapper around #ev_exec_t*.
Definition: exec.hpp:38
A future.
Definition: future.hpp:384
An abstract I/O device. This class is a wrapper around #io_dev_t*.
Definition: dev.hpp:35
A reference to an abstract timer.
Definition: timer.hpp:130
A wait operation suitable for use with a timerqueue.
Definition: tqueue.hpp:83
TimerQueueWait(ev_exec_t *exec, F &&f)
Constructs a wait operation with a completion task.
Definition: tqueue.hpp:89
ev::Executor get_executor() const noexcept
Returns the executor to which the completion task is (to be) submitted.
Definition: tqueue.hpp:117
TimerQueueWait(F &&f)
Constructs a wait operation with a completion task.
Definition: tqueue.hpp:106
A timer queue. This class is a wrapper around #io_tqueue_t*.
Definition: tqueue.hpp:126
TimerQueue(io_timer_t *timer, ev_exec_t *exec=nullptr)
Definition: tqueue.hpp:131
ev::Future< void, int > async_wait(ev_exec_t *exec, const TimerBase::time_point &t, struct io_tqueue_wait **pwait=nullptr)
Definition: tqueue.hpp:232
typename ::std::enable_if<!::std::is_base_of< io_tqueue_wait, typename ::std::decay< F >::type >::value >::type submit_wait(const TimerBase::duration &d, F &&f)
Definition: tqueue.hpp:214
void submit_wait(io_tqueue_wait &wait) noexcept
Definition: tqueue.hpp:169
void submit_wait(const TimerBase::time_point &t, io_tqueue_wait &wait) noexcept
Definition: tqueue.hpp:175
void submit_wait(const TimerBase::time_point &t, ev_exec_t *exec, F &&f)
Definition: tqueue.hpp:191
void submit_wait(const TimerBase::duration &d, io_tqueue_wait &wait)
Definition: tqueue.hpp:182
ev::Future< void, int > async_wait(const TimerBase::time_point &t, struct io_tqueue_wait **pwait=nullptr)
Definition: tqueue.hpp:242
void submit_wait(const TimerBase::duration &d, ev_exec_t *exec, F &&f)
Definition: tqueue.hpp:198
bool cancel_wait(struct io_tqueue_wait &wait) noexcept
Definition: tqueue.hpp:220
ev::Future< void, int > async_wait(const TimerBase::duration &d, struct io_tqueue_wait **pwait=nullptr)
Definition: tqueue.hpp:257
typename ::std::enable_if<!::std::is_base_of< io_tqueue_wait, typename ::std::decay< F >::type >::value >::type submit_wait(const TimerBase::time_point &t, F &&f)
Definition: tqueue.hpp:206
TimerBase get_timer() const noexcept
Definition: tqueue.hpp:163
ev::Future< void, int > async_wait(ev_exec_t *exec, const TimerBase::duration &d, struct io_tqueue_wait **pwait=nullptr)
Definition: tqueue.hpp:249
bool abort_wait(struct io_tqueue_wait &wait) noexcept
Definition: tqueue.hpp:226
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
Definition: ev.h:29
const struct io_timer_vtbl *const io_timer_t
An abstract timer.
Definition: timer.h:38
const struct io_dev_vtbl *const io_dev_t
An abstract I/O device.
Definition: dev.h:35
::std::error_code make_error_code(SdoErrc e) noexcept
Creates an error code corresponding to an SDO abort code.
Definition: sdo_error.cpp:170
An executable task.
Definition: task.h:41
A wait operation suitable for use with a timer queue.
Definition: tqueue.h:36
struct ev_task task
The task (to be) submitted upon completion (or cancellation) of the wait operation.
Definition: tqueue.h:43
struct timespec value
The absolute expiration time.
Definition: tqueue.h:38
Determines whether F can be invoked with the arguments Args....
This header file is part of the I/O library; it contains the C++ interface for the abstract timer.
This header file is part of the I/O library; it contains the timer queue declarations.
io_timer_t * io_tqueue_get_timer(const io_tqueue_t *tq)
Returns a pointer to the I/O timer used by the timer queue.
Definition: tqueue.c:228
void io_tqueue_destroy(io_tqueue_t *tq)
Destroys a timer queue.
Definition: tqueue.c:211
size_t io_tqueue_abort_wait(io_tqueue_t *tq, struct io_tqueue_wait *wait)
Aborts the specified timer queue wait operation if it is pending.
Definition: tqueue.c:313
size_t io_tqueue_cancel_wait(io_tqueue_t *tq, struct io_tqueue_wait *wait)
Cancels the specified timer queue wait operation if it is pending.
Definition: tqueue.c:294
ev_future_t * io_tqueue_async_wait(io_tqueue_t *tq, ev_exec_t *exec, const struct timespec *value, struct io_tqueue_wait **pwait)
Submits an asynchronous wait operation to a timer queue and creates a future which becomes ready once...
Definition: tqueue.c:332
struct io_tqueue_wait * io_tqueue_wait_from_task(struct ev_task *task)
Obtains a pointer to a timer queue wait operation from a pointer to its completion task.
Definition: tqueue.c:358
void io_tqueue_submit_wait(io_tqueue_t *tq, struct io_tqueue_wait *wait)
Submits a wait operation to a timer queue.
Definition: tqueue.c:236
#define IO_TQUEUE_WAIT_INIT(sec, nsec, exec, func)
The static initializer for io_tqueue_wait.
Definition: tqueue.h:53
io_tqueue_t * io_tqueue_create(io_timer_t *timer, ev_exec_t *exec)
Creates a new timer queue.
Definition: tqueue.c:184
io_dev_t * io_tqueue_get_dev(const io_tqueue_t *tq)
Returns a pointer to the abstract I/O device representing the timer queue.
Definition: tqueue.c:220
typename ::std::enable_if< compat::is_invocable< F, ::std::error_code >::value, detail::TimerQueueWaitWrapper< F > * >::type make_timer_queue_wait_wrapper(ev_exec_t *exec, F &&f)
Creates a wait operation with a completion task.
Definition: tqueue.hpp:73