Lely core libraries 2.3.4
timer.hpp
Go to the documentation of this file.
1
24#ifndef LELY_IO2_TIMER_HPP_
25#define LELY_IO2_TIMER_HPP_
26
27#include <lely/ev/future.hpp>
28#include <lely/io2/dev.hpp>
29#include <lely/io2/clock.hpp>
30#include <lely/io2/timer.h>
31
32#include <utility>
33
34namespace lely {
35namespace io {
36
37namespace detail {
38
39template <class F>
41 public:
42 TimerWaitWrapper(ev_exec_t* exec, F&& f)
44 exec,
45 [](ev_task* task) noexcept {
46 auto wait = io_timer_wait_from_task(task);
47 auto overrun = wait->r.result;
48 ::std::error_code ec;
49 if (overrun == -1) ec = util::make_error_code(wait->r.errc);
50 auto self = static_cast<TimerWaitWrapper*>(wait);
51 compat::invoke(::std::move(self->func_), overrun, ec);
52 delete self;
53 }),
54 func_(::std::forward<F>(f)) {}
55
56 TimerWaitWrapper(const TimerWaitWrapper&) = delete;
57
58 TimerWaitWrapper& operator=(const TimerWaitWrapper&) = delete;
59
60 private:
61 typename ::std::decay<F>::type func_;
62};
63
64} // namespace detail
65
71template <class F>
72inline typename ::std::enable_if<
76 return new detail::TimerWaitWrapper<F>(exec, ::std::forward<F>(f));
77}
78
84class TimerWait : public io_timer_wait {
85 public:
86 using Signature = void(int, ::std::error_code);
87
89 template <class F>
90 TimerWait(ev_exec_t* exec, F&& f)
93 [](ev_task* task) noexcept {
94 auto wait = io_timer_wait_from_task(task);
95 auto self = static_cast<TimerWait*>(wait);
96 if (self->func_) {
97 auto overrun = wait->r.result;
98 ::std::error_code ec;
99 if (overrun == -1)
100 ec = util::make_error_code(wait->r.errc);
101 self->func_(overrun, ec);
102 }
103 }),
104 func_(::std::forward<F>(f)) {}
105
107 template <class F>
108 explicit TimerWait(F&& f) : TimerWait(nullptr, ::std::forward<F>(f)) {}
109
110 TimerWait(const TimerWait&) = delete;
111
112 TimerWait& operator=(const TimerWait&) = delete;
113
114 operator ev_task&() & noexcept { return task; }
115
118 get_executor() const noexcept {
119 return ev::Executor(task.exec);
120 }
121
122 private:
123 ::std::function<Signature> func_;
124};
125
130class TimerBase : public Device {
131 public:
132 using Device::operator io_dev_t*;
133
134 using duration = Clock::duration;
135 using time_point = Clock::time_point;
136
137 explicit TimerBase(io_timer_t* timer_) noexcept
138 : Device(timer_ ? io_timer_get_dev(timer_) : nullptr), timer(timer_) {}
139
140 operator io_timer_t*() const noexcept { return timer; }
141
143 Clock
144 get_clock() const noexcept {
145 return Clock(io_timer_get_clock(*this));
146 }
147
149 int
150 getoverrun(::std::error_code& ec) const noexcept {
151 int errsv = get_errc();
152 set_errc(0);
153 int overrun = io_timer_getoverrun(*this);
154 if (overrun >= 0)
155 ec.clear();
156 else
158 set_errc(errsv);
159 return overrun;
160 }
161
163 int
164 getoverrun() const {
165 ::std::error_code ec;
166 int overrun = getoverrun(ec);
167 if (overrun < 0) throw ::std::system_error(ec, "getoverrun");
168 return overrun;
169 }
170
178 ::std::pair<duration, duration>
179 gettime(::std::error_code& ec) const noexcept {
180 int errsv = get_errc();
181 set_errc(0);
182 itimerspec value = {{0, 0}, {0, 0}};
183 if (!io_timer_gettime(*this, &value))
184 ec.clear();
185 else
187 set_errc(errsv);
188 return {util::from_timespec(value.it_value),
189 util::from_timespec(value.it_interval)};
190 }
191
199 ::std::pair<duration, duration>
200 gettime() const {
201 ::std::error_code ec;
202 auto value = gettime(ec);
203 if (ec) throw ::std::system_error(ec, "gettime");
204 return value;
205 }
206
208 ::std::pair<duration, duration>
209 settime(const duration& expiry, const duration& period,
210 ::std::error_code& ec) noexcept {
211 int errsv = get_errc();
212 set_errc(0);
213 itimerspec value = {util::to_timespec(period), util::to_timespec(expiry)};
214 itimerspec ovalue = {{0, 0}, {0, 0}};
215 if (!io_timer_settime(*this, 0, &value, &ovalue))
216 ec.clear();
217 else
219 set_errc(errsv);
220 return {util::from_timespec(ovalue.it_value),
221 util::from_timespec(ovalue.it_interval)};
222 }
223
225 ::std::pair<duration, duration>
226 settime(const duration& expiry, const duration& period = {}) {
227 ::std::error_code ec;
228 auto ovalue = settime(expiry, period, ec);
229 if (ec) throw ::std::system_error(ec, "settime");
230 return ovalue;
231 }
232
234 ::std::pair<duration, duration>
235 settime(const time_point& expiry, const duration& period,
236 ::std::error_code& ec) noexcept {
237 int errsv = get_errc();
238 set_errc(0);
239 itimerspec value = {util::to_timespec(period), util::to_timespec(expiry)};
240 itimerspec ovalue = {{0, 0}, {0, 0}};
241 if (!io_timer_settime(*this, TIMER_ABSTIME, &value, &ovalue))
242 ec.clear();
243 else
245 set_errc(errsv);
246 return {util::from_timespec(ovalue.it_value),
247 util::from_timespec(ovalue.it_interval)};
248 }
249
251 ::std::pair<duration, duration>
252 settime(const time_point& expiry, const duration& period = {}) {
253 ::std::error_code ec;
254 auto ovalue = settime(expiry, period, ec);
255 if (ec) throw ::std::system_error(ec, "settime");
256 return ovalue;
257 }
258
260 void
261 submit_wait(io_timer_wait& wait) noexcept {
262 io_timer_submit_wait(*this, &wait);
263 }
264
266 template <class F>
267 void
268 submit_wait(ev_exec_t* exec, F&& f) {
269 submit_wait(*make_timer_wait_wrapper(exec, ::std::forward<F>(f)));
270 }
271
273 template <class F>
274 typename ::std::enable_if<!::std::is_base_of<
275 io_timer_wait, typename ::std::decay<F>::type>::value>::type
276 submit_wait(F&& f) {
277 submit_wait(nullptr, ::std::forward<F>(f));
278 }
279
281 bool
282 cancel_wait(struct io_timer_wait& wait) noexcept {
283 return io_timer_cancel_wait(*this, &wait) != 0;
284 }
285
287 bool
288 abort_wait(struct io_timer_wait& wait) noexcept {
289 return io_timer_abort_wait(*this, &wait) != 0;
290 }
291
294 async_wait(ev_exec_t* exec, struct io_timer_wait** pwait = nullptr) {
295 auto future = io_timer_async_wait(*this, exec, pwait);
296 if (!future) util::throw_errc("async_wait");
297 return ev::Future<int, int>(future);
298 }
299
302 async_wait(struct io_timer_wait** pwait = nullptr) {
303 return async_wait(nullptr, pwait);
304 }
305
306 protected:
307 io_timer_t* timer{nullptr};
308};
309
310} // namespace io
311} // namespace lely
312
313#endif // !LELY_IO2_TIMER_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 clock. This class is a wrapper around #io_clock_t*.
Definition: clock.hpp:35
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
void submit_wait(io_timer_wait &wait) noexcept
Definition: timer.hpp:261
::std::pair< duration, duration > gettime(::std::error_code &ec) const noexcept
Definition: timer.hpp:179
bool abort_wait(struct io_timer_wait &wait) noexcept
Definition: timer.hpp:288
bool cancel_wait(struct io_timer_wait &wait) noexcept
Definition: timer.hpp:282
::std::pair< duration, duration > settime(const duration &expiry, const duration &period={})
Definition: timer.hpp:226
void submit_wait(ev_exec_t *exec, F &&f)
Definition: timer.hpp:268
int getoverrun(::std::error_code &ec) const noexcept
Definition: timer.hpp:150
int getoverrun() const
Definition: timer.hpp:164
Clock get_clock() const noexcept
Definition: timer.hpp:144
ev::Future< int, int > async_wait(struct io_timer_wait **pwait=nullptr)
Definition: timer.hpp:302
::std::pair< duration, duration > gettime() const
Definition: timer.hpp:200
typename::std::enable_if<!::std::is_base_of< io_timer_wait, typename::std::decay< F >::type >::value >::type submit_wait(F &&f)
Definition: timer.hpp:276
::std::pair< duration, duration > settime(const time_point &expiry, const duration &period={})
Definition: timer.hpp:252
::std::pair< duration, duration > settime(const time_point &expiry, const duration &period, ::std::error_code &ec) noexcept
Definition: timer.hpp:235
ev::Future< int, int > async_wait(ev_exec_t *exec, struct io_timer_wait **pwait=nullptr)
Definition: timer.hpp:294
::std::pair< duration, duration > settime(const duration &expiry, const duration &period, ::std::error_code &ec) noexcept
Definition: timer.hpp:209
A wait operation suitable for use with an I/O timer.
Definition: timer.hpp:84
ev::Executor get_executor() const noexcept
Returns the executor to which the completion task is (to be) submitted.
Definition: timer.hpp:118
TimerWait(ev_exec_t *exec, F &&f)
Constructs a wait operation with a completion task.
Definition: timer.hpp:90
TimerWait(F &&f)
Constructs a wait operation with a completion task.
Definition: timer.hpp:108
This header file is part of the I/O library; it contains the C++ interface for the abstract clock.
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
This header file is part of the event library; it contains the C++ interface for the futures and prom...
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
Definition: ev.h:29
This header file is part of the I/O library; it contains the abstract timer interface.
int io_timer_settime(io_timer_t *timer, int flags, const struct itimerspec *value, struct itimerspec *ovalue)
Arms or disarms an I/O timer.
Definition: timer.h:256
const struct io_timer_vtbl *const io_timer_t
An abstract timer.
Definition: timer.h:38
static size_t io_timer_abort_wait(io_timer_t *timer, struct io_timer_wait *wait)
Aborts the specified I/O timer wait operation if it is pending.
Definition: timer.h:275
static size_t io_timer_cancel_wait(io_timer_t *timer, struct io_timer_wait *wait)
Cancels the specified I/O timer wait operation if it is pending.
Definition: timer.h:269
ev_future_t * io_timer_async_wait(io_timer_t *timer, ev_exec_t *exec, struct io_timer_wait **pwait)
Submits an asynchronous wait operation to an I/O timer and creates a future which becomes ready once ...
Definition: timer.c:39
io_clock_t * io_timer_get_clock(const io_timer_t *timer)
Returns a pointer to the clock used by the timer.
Definition: timer.h:238
io_dev_t * io_timer_get_dev(const io_timer_t *timer)
Returns a pointer to the abstract I/O device representing the timer.
Definition: timer.h:232
void io_timer_submit_wait(io_timer_t *timer, struct io_timer_wait *wait)
Submits a wait operation to an I/O timer.
Definition: timer.h:263
struct io_timer_wait * io_timer_wait_from_task(struct ev_task *task)
Obtains a pointer to an I/O timer wait operation from a pointer to its completion task.
Definition: timer.c:62
int io_timer_getoverrun(const io_timer_t *timer)
Obtains the I/O timer expiration overrun count of the last successfully processed expiration.
Definition: timer.h:244
int io_timer_gettime(const io_timer_t *timer, struct itimerspec *value)
Obtains the amount of time until the specified I/O timer expires and the reload value of the timer.
Definition: timer.h:250
#define IO_TIMER_WAIT_INIT(exec, func)
The static initializer for io_timer_wait.
Definition: timer.h:65
const struct io_dev_vtbl *const io_dev_t
An abstract I/O device.
Definition: dev.h:35
This header file is part of the I/O library; it contains the C++ interface for the abstract I/O devic...
::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
int result
The result of the wait operation: the expiration overrun count (see io_timer_getoverrun()) on success...
Definition: timer.h:48
A wait operation suitable for use with an I/O timer.
Definition: timer.h:54
struct io_timer_wait_result r
The result of the wait operation.
Definition: timer.h:61
struct ev_task task
The task (to be) submitted upon completion (or cancellation) of the wait operation.
Definition: timer.h:59
Determines whether F can be invoked with the arguments Args....
typename::std::enable_if< compat::is_invocable< F, int,::std::error_code >::value, detail::TimerWaitWrapper< F > * >::type make_timer_wait_wrapper(ev_exec_t *exec, F &&f)
Creates a wait operation with a completion task.
Definition: timer.hpp:75