timer, timer_impl
// Members of dasynq::event_loop<T> instantiation: class timer; template <class Derived> class timer_impl; // : public timer;
timer
Brief: timer is a member type of the event_loop template class. It represents an event watcher which receives callbacks upon the passing of a certain period of time, or at a certain time, against either the system clock (which can potentially have its time altered during system operation) or a monotonic clock which is not adjustable. The timer class should not be subclassed directly; the timer_impl template provides a means for subclassing.
Members
Types
- event_loop_t — the event loop type that this watcher registers with.
Constructors
- timer() — default constructor.
Functions
- (#1) void add_timer(event_loop_t &eloop, clock_type clock = clock_type::MONOTONIC, int prio = DEFAULT_PRIORITY)
— register a timer using the specified clock with an event loop. May throw std::bad_alloc or std::system_error. - (#2) template <typename T> static void add_timer(event_loop_t &eloop,
clock_type clock, const timespec &timeout, const timespec &interval,
T handler)
— add a dynamically-allocated timer using the specified clock, timeout and interval. The timer is automatically deleted when removed. See details below. May throw std::bad_alloc or std::system_error. - (#1) void arm_timer(event_loop_t &eloop, const timespec &timeout) noexcept
— arm a one-shot timer with the specified absolute timeout. - (#2) void arm_timer(event_loop_t &eloop, const timespec &timeout, const timespec &interval) noexcept
— arm a periodic timer with the specified initial absolute timeout and the specified interval period. - (#1) void arm_timer_rel(event_loop_t &eloop, const timespec &timeout) noexcept
— arm a one-shot timer with the specified relative timeout. - (#2) void arm_timer_rel(event_loop_t &eloop, const timespec &timeout, const timespec &interval) noexcept
— arm a periodic timer with the specified initial relative timeout and the specified interval period. - void stop_timer(event_loop_t &eloop) noexcept
— stop a timer, so that it stops counting intervals. - void set_enabled(event_loop_t &eloop, bool enable) noexcept — enable or disable the watcher. A disabled timer watcher does not have its callback called upon timer expiration, but the underlying timer continues to count (and repeat if periodic). A disabled timer watcher that has timeouts pending when enabled will report them as soon as the event loop is polled.
- void deregister(event_loop_t &eloop) noexcept
— request removal from the event loop. - virtual void watch_removed() noexcept — called when the watcher has been removed from the event loop.
Details and Usage
A timer represents a timer which expires at some point in time and an associated watcher which receives callback notifications for timer expiry. Timers can be one-shot (stop automatically after expiry) or periodic (on expiry, the timeout is incremented by a specified interval).
Note: also see the watcher constraints section.
A timer can run on one of two clocks, specified by a clock_type. The SYSTEM clock is the current "wall clock" time according to the system; its time value should normally only increase at a constant rate, but may be altered by large amounts in either direction if the system clock is altered. The MONOTONIC clock always increments at a constant rate and cannot be altered otherwise.
When a timer is set, the initial timeout can be specified either as an absolute time, or to a time that is relative to the current time. While setting relative times to the SYSTEM clock is supported, be aware that it rarely makes sense to do so; the timer is not guaranteed to expire after the specified interval (if the system clock is adjusted, the adjustment will also be applied to the timeout). Use a timer against the MONOTONIC clock if you need a specific interval of time.
An absolute timeout of 0:0 is not supported (some timer backends use it internally to disable the associated system timer).
Subclassing timer
To specify callback behaviour, timer can be subclassed — however, it should not be directly subclassed; instead, use the timer_impl implementation wrapper template.
timer_impl
Brief: The timer_impl provides a basis for implementing timer, using the "curiously recurring template pattern". Instead of subclassing timer directly, subclass an instantiation of timer_impl with the template parameter specified as the subclass itself. For example:
class my_timer : public timer_impl<my_timer> { // ... }
Details and Usage
The callback function must be provided in the subclass and named fd_event, with a signature compatible with the following:
rearm timer_expiry(event_loop_t &loop, int expiry_count);
The timer_expiry function must be public, but need not be virtual. It will be called with the following parameters:
- loop — a reference to the event loop.
- expiry_count — the number of times the timer expired before the watcher was queued for processing. Normally, this should be one, and for a one-shot timer it can only be one. However, for periodic timers, under a heavy system load or if the timer was disabled for a period, it may report a higher value.
The return value specifies the rearm action.
An timer_impl instantiation has no public or protected members, other than those inherited from timer_watcher, which it publicly derives from.
add_timer (#2)
// member of dasynq::event_loop<T>::timer template <typename T> static timer<event_loop_t> *add_timer(event_loop_t &eloop, clock_type clock, const timespec &timeout, const timespec &interval, T handler)
This variant of the add_timer function can be used to create and register a dynamically-allocated timer. This both creates and arms the timer in a single step; the parameters are as for add_timer(#1) and arm_timer, while the additional handler parameter is a function or lambda of the form:
[](event_loop_t &eloop, int expiry_count) -> rearm { ... }
It acts as the callback function for the generated timer. The watcher will delete itself when it is removed from the event loop (including if the callback returns rearm::REMOVE).
This add_timer function can throw std::system_error or std::bad_alloc on failure.