Click Timer objects trigger the execution of code after a specific time. Click's version of "ping" (the ICMPPingSource element) uses Timer objects to create ping packets at specific times. Many other elements, such as IPRewriter, garbage-collect their internal state based on timers. An element that needs to run occasional timed tasks includes and initializes a Timer instance variable. When scheduled, most timers call their associated element's run_timer() method.
Each scheduled Timer has a single expiration Timestamp. To implement a periodic timer, reschedule the timer as appropriate.
This example element code, based on TimedSource, will print a message every 5 seconds:
#include <click/element.hh> #include <click/timer.hh> class PeriodicPrinter : public Element { public: PeriodicPrinter(); const char *class_name() const { return "PeriodicPrinter"; } int initialize(ErrorHandler *errh); void run_timer(Timer *timer); private: Timer _timer; }; PeriodicPrinter::PeriodicPrinter() : _timer(this) // Sets _timer to call this->run_timer(&_timer) { // when it fires. } int PeriodicPrinter::initialize(ErrorHandler *) { _timer.initialize(this); // Initialize timer object (mandatory). _timer.schedule_now(); // Set the timer to fire as soon as the // router runs. return 0; } void PeriodicPrinter::run_timer(Timer *timer) { // This function is called when the timer fires. assert(timer == &_timer); Timestamp now = Timestamp::now(); click_chatter("%s: %{timestamp}: timer fired with expiry %{timestamp}!\n", declaration().c_str(), &now, &_timer.expiry()); // _timer.expiry() is the Timestamp at which the timer // was set to fire. _timer.reschedule_after_sec(5); // Fire again 5 seconds later. }
Running this element might produce output like this:
pp: 1204658365.127870: timer fired with expiry 1204658365.127847! pp: 1204658370.127911: timer fired with expiry 1204658370.127847! pp: 1204658375.127877: timer fired with expiry 1204658375.127847! pp: 1204658380.127874: timer fired with expiry 1204658380.127847! pp: 1204658385.127876: timer fired with expiry 1204658385.127847! pp: 1204658390.127926: timer fired with expiry 1204658390.127847! pp: 1204658395.128044: timer fired with expiry 1204658395.127847!
The expiry time measures when the timer was supposed to fire, while Timestamp::now() reports the current system time. Note that the timer's expiry time goes up by exactly 5 seconds each time, and that system time is always later than the expiry time.
Click aims to fire the timer as soon as possible after the expiry time, but cannot hit the expiry time exactly. The reschedule_after_sec() function and its variants (reschedule_after(), reschedule_after_msec()) schedule the next firing based on the previous expiry time. This makes the timer's action more robust to runtime fluctuations. Compare:
void PeriodicPrinter::run_timer(Timer *timer) { Timestamp now = Timestamp::now(); click_chatter("%s: %{timestamp}: timer fired with expiry %{timestamp}!\n", name().c_str(), &now, &_timer.expiry()); _timer.schedule_after_sec(5); // Fire again 5 seconds later. // This is the same as: // _timer.schedule_at(Timestamp::now() + Timestamp::make_sec(5)); }
The schedule_after_sec() function sets the timer to fire an interval after the current system time, not the previous expiry. As a result, the timer drifts:
pp: 1204658494.374277: timer fired with expiry 1204658494.374256! pp: 1204658499.374575: timer fired with expiry 1204658499.374478! pp: 1204658504.375261: timer fired with expiry 1204658504.375218! pp: 1204658509.375428: timer fired with expiry 1204658509.375381! ... pp: 1204658884.998112: timer fired with expiry 1204658884.998074! pp: 1204658890.001909: timer fired with expiry 1204658889.998209! pp: 1204658895.002399: timer fired with expiry 1204658895.002175! pp: 1204658900.003626: timer fired with expiry 1204658900.003589!
Timers that are set to fire more than 1 second in the past are silently updated to the current system time. Thus, the reschedule_after() methods will never fall more than a second or two behind system time.
Elements desiring extremely frequent access to the CPU, up to tens of thousands of times a second, should use a Task object rather than a Timer. However, Tasks essentially busy-wait, taking up all available CPU. There is a tradeoff, and some elements combine a Task and a Timer to get the benefits of both; for example, LinkUnqueue uses a Task at high rates and a Timer at low rates. The Timer::adjustment() value is useful in this context.
Particularly at user level, there can be a significant delay between a Timer's nominal expiration time and the actual time it runs. Elements that desire extremely precise timings should combine a Timer with a Task. The Timer is set to go off a bit before the true expiration time (see Timer::adjustment()), after which the Task polls the CPU until the actual expiration time arrives.
Since Click is cooperatively scheduled, any timer callback should run for just a short period of time. Very long callbacks can inappropriately delay other timers and periodic events.
The Click core stores timers in a heap, so most timer operations (including scheduling and unscheduling) take O(log n) time and Click can handle very large numbers of timers.
Timers generally run in increasing order by expiration time. That is, if timer a's expiry() is less than timer b's expiry(), then a will generally fire before b. However, Click must sometimes run timers out of order to ensure fairness. The only strict guarantee is that a Timer will run after its nominal expiration time.
Public Types | |
| enum | { behind_sec = 1 } |
Public Member Functions | |
| Timer () | |
| Construct a Timer that does nothing when fired. | |
| Timer (const do_nothing_t &unused) | |
| Construct a Timer that does nothing when fired. | |
| Timer (TimerCallback f, void *user_data) | |
| Construct a Timer that calls f(this, user_data) when fired. | |
| Timer (Element *element) | |
| Construct a Timer that calls element ->run_timer(this) when fired. | |
| Timer (Task *task) | |
| Construct a Timer that schedules task when fired. | |
| Timer (const Timer &x) | |
| Construct a Timer that acts like x when fired. | |
| ~Timer () | |
| Destroy a Timer, unscheduling it first if necessary. | |
| void | assign (const do_nothing_t &unused) |
| Change the Timer to do nothing when fired. | |
| void | assign (TimerCallback f, void *user_data) |
| Change the Timer to call f(this, user_data) when fired. | |
| void | assign (Element *element) |
| Change the Timer to call element ->run_timer(this) when fired. | |
| void | assign (Task *task) |
| Change the Timer to schedule task when fired. | |
| bool | initialized () const |
| Return true iff the Timer has been initialized. | |
| bool | scheduled () const |
| Return true iff the Timer is currently scheduled. | |
| const Timestamp & | expiry () const |
| Return the Timer's current expiration time. | |
| Router * | router () const |
| Return the Timer's associated Router. | |
| void | initialize (Element *owner, bool quiet=false) |
| Initialize the timer. | |
| void | initialize (Router *router) |
| Initialize the timer. | |
| void | schedule_at (const Timestamp &when) |
| Schedule the timer to fire at when. | |
| void | reschedule_at (const Timestamp &when) |
| Schedule the timer to fire at when. | |
| void | schedule_now () |
| Shedule the timer to fire immediately. | |
| void | schedule_after (const Timestamp &delta) |
| Schedule the timer to fire delta time in the future. | |
| void | schedule_after_sec (uint32_t delta_sec) |
| Schedule the timer to fire after delta_sec seconds. | |
| void | schedule_after_msec (uint32_t delta_msec) |
| Schedule the timer to fire after delta_msec milliseconds. | |
| void | reschedule_after (const Timestamp &delta) |
| Schedule the timer to fire delta time after its previous expiry. | |
| void | reschedule_after_sec (uint32_t delta_sec) |
| Schedule the timer to fire delta_sec seconds after its previous expiry. | |
| void | reschedule_after_msec (uint32_t delta_msec) |
| Schedule the timer to fire delta_msec milliseconds after its previous expiry. | |
| void | unschedule () |
| Unschedule the timer. | |
| void | clear () |
| Unschedule the timer and reset its expiration time. | |
| void | schedule_after_s (uint32_t delta_sec) |
| Schedule the timer to fire after delta_sec seconds (deprecated). | |
| void | schedule_after_ms (uint32_t delta_sec) |
| Schedule the timer to fire after delta_msec milliseconds (deprecated). | |
| void | reschedule_after_s (uint32_t delta_sec) |
| Schedule the timer to fire delta_sec seconds after its previous expiry time (deprecated). | |
| void | reschedule_after_ms (uint32_t delta_sec) |
| Schedule the timer to fire delta_msec milliseconds after its previous expiry time (deprecated). | |
Static Public Member Functions | |
| static Timestamp | adjustment () |
| Return an adjustment interval useful for precise timers. | |
Classes | |
| struct | do_nothing_t |
| Timer::Timer | ( | ) |
Construct a Timer that does nothing when fired.
This constructor is most useful for a Timer that will be assigned a true callback later, using one of the Timer::assign() methods. Timer::initialize() will report a warning if called on a Timer created by this constructor.
| Timer::Timer | ( | const do_nothing_t & | unused | ) |
Construct a Timer that does nothing when fired.
Unlike with the default Timer() constructor, Timer::initialize() will not report a warning if called on a Timer created by this constructor.
| Timer::Timer | ( | TimerCallback | f, | |
| void * | user_data | |||
| ) |
Construct a Timer that calls f(this, user_data) when fired.
| f | callback function | |
| user_data | argument for callback function |
| Timer::Timer | ( | Element * | element | ) |
| Timer::Timer | ( | Task * | task | ) |
| Timer::Timer | ( | const Timer & | x | ) |
| Timer::~Timer | ( | ) | [inline] |
Destroy a Timer, unscheduling it first if necessary.
| void Timer::assign | ( | const do_nothing_t & | unused | ) | [inline] |
Change the Timer to do nothing when fired.
| void Timer::assign | ( | TimerCallback | f, | |
| void * | user_data | |||
| ) | [inline] |
Change the Timer to call f(this, user_data) when fired.
| f | callback function | |
| user_data | argument for callback function |
| void Timer::assign | ( | Element * | element | ) | [inline] |
| void Timer::assign | ( | Task * | task | ) | [inline] |
| bool Timer::initialized | ( | ) | const [inline] |
Return true iff the Timer has been initialized.
| bool Timer::scheduled | ( | ) | const [inline] |
Return true iff the Timer is currently scheduled.
| const Timestamp& Timer::expiry | ( | ) | const [inline] |
Return the Timer's current expiration time.
The expiration time is the absolute time at which the timer is next scheduled to fire. If the timer is not currently scheduled, then expiry() returns the last assigned expiration time.
| void Timer::initialize | ( | Element * | owner, | |
| bool | quiet = false | |||
| ) | [inline] |
Initialize the timer.
| owner | the owner element | |
| quiet | do not produce default-constructor warning if true |
If Click is compiled with statistics support, time spent in this Timer will be charged to the owner element.
Initializing a Timer constructed by the default constructor, Timer(), will produce a warning.
| void Timer::initialize | ( | Router * | router | ) |
Initialize the timer.
| router | the owner router |
| void Timer::schedule_at | ( | const Timestamp & | when | ) |
Schedule the timer to fire at when.
| when | expiration time |
| void Timer::reschedule_at | ( | const Timestamp & | when | ) | [inline] |
Schedule the timer to fire at when.
| when | expiration time |
| void Timer::schedule_now | ( | ) | [inline] |
Shedule the timer to fire immediately.
Equivalent to schedule_at(Timestamp::now()).
| void Timer::schedule_after | ( | const Timestamp & | delta | ) |
Schedule the timer to fire delta time in the future.
| delta | interval until expiration time |
| void Timer::schedule_after_sec | ( | uint32_t | delta_sec | ) | [inline] |
Schedule the timer to fire after delta_sec seconds.
| delta_sec | interval until expiration time, in seconds |
| void Timer::schedule_after_msec | ( | uint32_t | delta_msec | ) | [inline] |
Schedule the timer to fire after delta_msec milliseconds.
| delta_msec | interval until expiration time, in milliseconds |
| void Timer::reschedule_after | ( | const Timestamp & | delta | ) | [inline] |
Schedule the timer to fire delta time after its previous expiry.
| delta | interval until expiration time |
| void Timer::reschedule_after_sec | ( | uint32_t | delta_sec | ) | [inline] |
Schedule the timer to fire delta_sec seconds after its previous expiry.
| delta_sec | interval until expiration time, in seconds |
| void Timer::reschedule_after_msec | ( | uint32_t | delta_msec | ) | [inline] |
Schedule the timer to fire delta_msec milliseconds after its previous expiry.
| delta_msec | interval until expiration time, in milliseconds |
| void Timer::unschedule | ( | ) |
Unschedule the timer.
The timer's expiration time is not modified.
| void Timer::clear | ( | ) | [inline] |
Unschedule the timer and reset its expiration time.
| static Timestamp Timer::adjustment | ( | ) | [inline, static] |
Return an adjustment interval useful for precise timers.
Due to scheduling granularity, other tasks running on the same machine, and similar effects, a Timer object can trigger some time after its nominal expiry(). Functions that require precise timers should combine a Timer and a Task object. The Timer's job is to schedule the Task; the Timer's expiry is set to go off a short interval before the true expiry, and the Task is used to busy-wait the difference. Timer::adjustment() is an appropriate value for this time difference.
| void Timer::schedule_after_s | ( | uint32_t | delta_sec | ) | [inline] |
Schedule the timer to fire after delta_sec seconds (deprecated).
| void Timer::schedule_after_ms | ( | uint32_t | delta_sec | ) | [inline] |
Schedule the timer to fire after delta_msec milliseconds (deprecated).
| void Timer::reschedule_after_s | ( | uint32_t | delta_sec | ) | [inline] |
Schedule the timer to fire delta_sec seconds after its previous expiry time (deprecated).
| void Timer::reschedule_after_ms | ( | uint32_t | delta_sec | ) | [inline] |
Schedule the timer to fire delta_msec milliseconds after its previous expiry time (deprecated).
1.5.1