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
32namespace lely {
33namespace io {
34
35namespace detail {
36
37template <class F>
39 public:
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
68template <class F>
69// clang-format off
70inline 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>
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
126class 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
ev::Future< void, int > async_wait(ev_exec_t *exec, const TimerBase::duration &d, struct io_tqueue_wait **pwait=nullptr)
Definition: tqueue.hpp:249
TimerQueue(io_timer_t *timer, ev_exec_t *exec=nullptr)
Definition: tqueue.hpp:131
void submit_wait(io_tqueue_wait &wait) noexcept
Definition: tqueue.hpp:169
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
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
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
bool cancel_wait(struct io_tqueue_wait &wait) noexcept
Definition: tqueue.hpp:220
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
TimerBase get_timer() const noexcept
Definition: tqueue.hpp:163
ev::Future< void, int > async_wait(const TimerBase::duration &d, struct io_tqueue_wait **pwait=nullptr)
Definition: tqueue.hpp:257
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
STL namespace.
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.
void io_tqueue_destroy(io_tqueue_t *tq)
Destroys a timer queue.
Definition: tqueue.c:211
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
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
io_tqueue_t * io_tqueue_create(io_timer_t *timer, ev_exec_t *exec)
Creates a new timer queue.
Definition: tqueue.c:184
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
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
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_submit_wait(io_tqueue_t *tq, struct io_tqueue_wait *wait)
Submits a wait operation to a timer queue.
Definition: tqueue.c:236
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
#define IO_TQUEUE_WAIT_INIT(sec, nsec, exec, func)
The static initializer for io_tqueue_wait.
Definition: tqueue.h:53
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