Periodic Timer
Loading...
Searching...
No Matches
Periodic Timer, Lightweight Timer Utility Using Asio

Overview

The periodic_timer class template is an asynchronous periodic timer that wraps and simplifies Asio timers when periodic callbacks are needed. The periodicity can be based on either a simple duration or on timepoints based on a duration. When the timer is started, the application specifies whether each callback is invoked based on a duration (e.g. one second after the last callback), or on timepoints (e.g. a callback will be invoked each second according to the clock).

The Asio library does not directly provide periodic timers. Instead, application code using Asio must chain together function object callbacks until satisfied.

The periodic_timer class template is a thin wrapper supplying the chaining, with two options for the periodicity. In addition, elapsed times are computed and provided to the application supplied callback.

One periodicity option is to invoke the application callback after a duration. It is simple and provides consistency, specially if the system clock is allowed to be adjusted.

The second periodicity option is to invoke the application callback based on timepoints. This works well in environments where activities must be processed on regular time intervals, regardless of how much processing is performed in each application callback. For example, an application may desire a timer callback to be invoked once every 500 milliseconds and the callback takes 15 milliseconds to excecute. Also occasionally the operating environment takes an extra 10 or 20 milliseconds before invoking the callback. Using a duration instead of a timepoint the actual interval is now 515 milliseconds between callback invocations, with occasional intervals up to 535 milliseconds. A timepoint timer will instead invoke the callback every 500 milliseconds (depending on operating system precision and load) regardless of how much time is taken by the previous callback.

The main disadvantange of timepoint based callbacks is that they can be affected by system clock adjustments. In addition, if the timepoint interval is small and a large amount of processing is performed by the callback, "overflow" can occur, where the next timepoint callback is overrun by the current processing.

An excellent article on this topic by Tony DaSilva can be [read here] (https://bulldozer00.blog/2013/12/27/periodic-processing-with-standard-c11-facilities/).

An asynchronous timer is more resource-friendly regarding system resources than creating a thread that sleeps. In particular, creating hundreds or thousands of timers is very expensive in a "thread per timer" design.

Additional Details

periodic_timer is a class template corresponding to a single timer object. Designs needing many periodic timer objects, possibly sorted by time (e.g. a priority queue based on a time stamp) will need to create their own containers and data structures, using periodic_timer as a container element.

Asynchronous processing is performed by the Asio io_context (C++ executor context) passed in to the constructor by the application.

A periodic_timer stops when the application supplied function object returns false rather than true.

A periodic timer can be used as a "one-shot" timer by finishing after one invocation (i.e. unconditionally return false from the function object).

Note
This class does not perform "this" reference counting. It is up to the application code to guarantee that a periodic_timer has not been destructed before handlers (function object callbacks) are invoked.

A common idiom is to use std::enable_shared_from_this, call std::shared_from_this, and store the result in the function object callback object.

Note
std::chrono facilities seem to be underspecified on noexcept, very few of the functions in periodic_timer are noexcept.
Author
Cliff Green

Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)