1258945Sroberto/* 2280849Scy * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") 3258945Sroberto * Copyright (C) 1998-2002 Internet Software Consortium. 4258945Sroberto * 5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any 6258945Sroberto * purpose with or without fee is hereby granted, provided that the above 7258945Sroberto * copyright notice and this permission notice appear in all copies. 8258945Sroberto * 9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11258945Sroberto * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15258945Sroberto * PERFORMANCE OF THIS SOFTWARE. 16258945Sroberto */ 17258945Sroberto 18280849Scy/* $Id: timer.h,v 1.43 2009/09/02 23:48:03 tbox Exp $ */ 19258945Sroberto 20258945Sroberto#ifndef ISC_TIMER_H 21258945Sroberto#define ISC_TIMER_H 1 22258945Sroberto 23258945Sroberto/***** 24258945Sroberto ***** Module Info 25258945Sroberto *****/ 26258945Sroberto 27258945Sroberto/*! \file isc/timer.h 28258945Sroberto * \brief Provides timers which are event sources in the task system. 29258945Sroberto * 30258945Sroberto * Three types of timers are supported: 31258945Sroberto * 32258945Sroberto *\li 'ticker' timers generate a periodic tick event. 33258945Sroberto * 34258945Sroberto *\li 'once' timers generate an idle timeout event if they are idle for too 35258945Sroberto * long, and generate a life timeout event if their lifetime expires. 36258945Sroberto * They are used to implement both (possibly expiring) idle timers and 37258945Sroberto * 'one-shot' timers. 38258945Sroberto * 39258945Sroberto *\li 'limited' timers generate a periodic tick event until they reach 40258945Sroberto * their lifetime when they generate a life timeout event. 41258945Sroberto * 42258945Sroberto *\li 'inactive' timers generate no events. 43258945Sroberto * 44258945Sroberto * Timers can change type. It is typical to create a timer as 45258945Sroberto * an 'inactive' timer and then change it into a 'ticker' or 46258945Sroberto * 'once' timer. 47258945Sroberto * 48258945Sroberto *\li MP: 49258945Sroberto * The module ensures appropriate synchronization of data structures it 50258945Sroberto * creates and manipulates. 51258945Sroberto * Clients of this module must not be holding a timer's task's lock when 52258945Sroberto * making a call that affects that timer. Failure to follow this rule 53258945Sroberto * can result in deadlock. 54258945Sroberto * The caller must ensure that isc_timermgr_destroy() is called only 55258945Sroberto * once for a given manager. 56258945Sroberto * 57258945Sroberto * \li Reliability: 58258945Sroberto * No anticipated impact. 59258945Sroberto * 60258945Sroberto * \li Resources: 61258945Sroberto * TBS 62258945Sroberto * 63258945Sroberto * \li Security: 64258945Sroberto * No anticipated impact. 65258945Sroberto * 66258945Sroberto * \li Standards: 67258945Sroberto * None. 68258945Sroberto */ 69258945Sroberto 70258945Sroberto 71258945Sroberto/*** 72258945Sroberto *** Imports 73258945Sroberto ***/ 74258945Sroberto 75258945Sroberto#include <isc/types.h> 76258945Sroberto#include <isc/event.h> 77258945Sroberto#include <isc/eventclass.h> 78258945Sroberto#include <isc/lang.h> 79258945Sroberto#include <isc/time.h> 80258945Sroberto 81258945SrobertoISC_LANG_BEGINDECLS 82258945Sroberto 83258945Sroberto/*** 84258945Sroberto *** Types 85258945Sroberto ***/ 86258945Sroberto 87258945Sroberto/*% Timer Type */ 88258945Srobertotypedef enum { 89258945Sroberto isc_timertype_ticker = 0, /*%< Ticker */ 90258945Sroberto isc_timertype_once = 1, /*%< Once */ 91258945Sroberto isc_timertype_limited = 2, /*%< Limited */ 92258945Sroberto isc_timertype_inactive = 3 /*%< Inactive */ 93258945Sroberto} isc_timertype_t; 94258945Sroberto 95258945Srobertotypedef struct isc_timerevent { 96258945Sroberto struct isc_event common; 97258945Sroberto isc_time_t due; 98258945Sroberto} isc_timerevent_t; 99258945Sroberto 100258945Sroberto#define ISC_TIMEREVENT_FIRSTEVENT (ISC_EVENTCLASS_TIMER + 0) 101258945Sroberto#define ISC_TIMEREVENT_TICK (ISC_EVENTCLASS_TIMER + 1) 102258945Sroberto#define ISC_TIMEREVENT_IDLE (ISC_EVENTCLASS_TIMER + 2) 103258945Sroberto#define ISC_TIMEREVENT_LIFE (ISC_EVENTCLASS_TIMER + 3) 104258945Sroberto#define ISC_TIMEREVENT_LASTEVENT (ISC_EVENTCLASS_TIMER + 65535) 105258945Sroberto 106280849Scy/*% Timer and timer manager methods */ 107280849Scytypedef struct { 108280849Scy void (*destroy)(isc_timermgr_t **managerp); 109280849Scy isc_result_t (*timercreate)(isc_timermgr_t *manager, 110280849Scy isc_timertype_t type, 111280849Scy isc_time_t *expires, 112280849Scy isc_interval_t *interval, 113280849Scy isc_task_t *task, 114280849Scy isc_taskaction_t action, 115280849Scy const void *arg, 116280849Scy isc_timer_t **timerp); 117280849Scy} isc_timermgrmethods_t; 118280849Scy 119280849Scytypedef struct { 120280849Scy void (*attach)(isc_timer_t *timer, isc_timer_t **timerp); 121280849Scy void (*detach)(isc_timer_t **timerp); 122280849Scy isc_result_t (*reset)(isc_timer_t *timer, isc_timertype_t type, 123280849Scy isc_time_t *expires, isc_interval_t *interval, 124280849Scy isc_boolean_t purge); 125280849Scy isc_result_t (*touch)(isc_timer_t *timer); 126280849Scy} isc_timermethods_t; 127280849Scy 128280849Scy/*% 129280849Scy * This structure is actually just the common prefix of a timer manager 130280849Scy * object implementation's version of an isc_timermgr_t. 131280849Scy * \brief 132280849Scy * Direct use of this structure by clients is forbidden. timer implementations 133280849Scy * may change the structure. 'magic' must be ISCAPI_TIMERMGR_MAGIC for any 134280849Scy * of the isc_timer_ routines to work. timer implementations must maintain 135280849Scy * all timer invariants. 136280849Scy */ 137280849Scystruct isc_timermgr { 138280849Scy unsigned int impmagic; 139280849Scy unsigned int magic; 140280849Scy isc_timermgrmethods_t *methods; 141280849Scy}; 142280849Scy 143280849Scy#define ISCAPI_TIMERMGR_MAGIC ISC_MAGIC('A','t','m','g') 144280849Scy#define ISCAPI_TIMERMGR_VALID(m) ((m) != NULL && \ 145280849Scy (m)->magic == ISCAPI_TIMERMGR_MAGIC) 146280849Scy 147280849Scy/*% 148280849Scy * This is the common prefix of a timer object. The same note as 149280849Scy * that for the timermgr structure applies. 150280849Scy */ 151280849Scystruct isc_timer { 152280849Scy unsigned int impmagic; 153280849Scy unsigned int magic; 154280849Scy isc_timermethods_t *methods; 155280849Scy}; 156280849Scy 157280849Scy#define ISCAPI_TIMER_MAGIC ISC_MAGIC('A','t','m','r') 158280849Scy#define ISCAPI_TIMER_VALID(s) ((s) != NULL && \ 159280849Scy (s)->magic == ISCAPI_TIMER_MAGIC) 160280849Scy 161258945Sroberto/*** 162258945Sroberto *** Timer and Timer Manager Functions 163258945Sroberto *** 164258945Sroberto *** Note: all Ensures conditions apply only if the result is success for 165258945Sroberto *** those functions which return an isc_result_t. 166258945Sroberto ***/ 167258945Sroberto 168258945Srobertoisc_result_t 169258945Srobertoisc_timer_create(isc_timermgr_t *manager, 170258945Sroberto isc_timertype_t type, 171258945Sroberto isc_time_t *expires, 172258945Sroberto isc_interval_t *interval, 173258945Sroberto isc_task_t *task, 174258945Sroberto isc_taskaction_t action, 175258945Sroberto const void *arg, 176258945Sroberto isc_timer_t **timerp); 177258945Sroberto/*%< 178258945Sroberto * Create a new 'type' timer managed by 'manager'. The timers parameters 179258945Sroberto * are specified by 'expires' and 'interval'. Events will be posted to 180258945Sroberto * 'task' and when dispatched 'action' will be called with 'arg' as the 181258945Sroberto * arg value. The new timer is returned in 'timerp'. 182258945Sroberto * 183258945Sroberto * Notes: 184258945Sroberto * 185258945Sroberto *\li For ticker timers, the timer will generate a 'tick' event every 186258945Sroberto * 'interval' seconds. The value of 'expires' is ignored. 187258945Sroberto * 188258945Sroberto *\li For once timers, 'expires' specifies the time when a life timeout 189258945Sroberto * event should be generated. If 'expires' is 0 (the epoch), then no life 190258945Sroberto * timeout will be generated. 'interval' specifies how long the timer 191258945Sroberto * can be idle before it generates an idle timeout. If 0, then no 192258945Sroberto * idle timeout will be generated. 193258945Sroberto * 194258945Sroberto *\li If 'expires' is NULL, the epoch will be used. 195258945Sroberto * 196258945Sroberto * If 'interval' is NULL, the zero interval will be used. 197258945Sroberto * 198258945Sroberto * Requires: 199258945Sroberto * 200258945Sroberto *\li 'manager' is a valid manager 201258945Sroberto * 202258945Sroberto *\li 'task' is a valid task 203258945Sroberto * 204258945Sroberto *\li 'action' is a valid action 205258945Sroberto * 206258945Sroberto *\li 'expires' points to a valid time, or is NULL. 207258945Sroberto * 208258945Sroberto *\li 'interval' points to a valid interval, or is NULL. 209258945Sroberto * 210258945Sroberto *\li type == isc_timertype_inactive || 211258945Sroberto * ('expires' and 'interval' are not both 0) 212258945Sroberto * 213258945Sroberto *\li 'timerp' is a valid pointer, and *timerp == NULL 214258945Sroberto * 215258945Sroberto * Ensures: 216258945Sroberto * 217258945Sroberto *\li '*timerp' is attached to the newly created timer 218258945Sroberto * 219258945Sroberto *\li The timer is attached to the task 220258945Sroberto * 221258945Sroberto *\li An idle timeout will not be generated until at least Now + the 222258945Sroberto * timer's interval if 'timer' is a once timer with a non-zero 223258945Sroberto * interval. 224258945Sroberto * 225258945Sroberto * Returns: 226258945Sroberto * 227258945Sroberto *\li Success 228258945Sroberto *\li No memory 229258945Sroberto *\li Unexpected error 230258945Sroberto */ 231258945Sroberto 232258945Srobertoisc_result_t 233258945Srobertoisc_timer_reset(isc_timer_t *timer, 234258945Sroberto isc_timertype_t type, 235258945Sroberto isc_time_t *expires, 236258945Sroberto isc_interval_t *interval, 237258945Sroberto isc_boolean_t purge); 238258945Sroberto/*%< 239258945Sroberto * Change the timer's type, expires, and interval values to the given 240258945Sroberto * values. If 'purge' is TRUE, any pending events from this timer 241258945Sroberto * are purged from its task's event queue. 242258945Sroberto * 243258945Sroberto * Notes: 244258945Sroberto * 245258945Sroberto *\li If 'expires' is NULL, the epoch will be used. 246258945Sroberto * 247258945Sroberto *\li If 'interval' is NULL, the zero interval will be used. 248258945Sroberto * 249258945Sroberto * Requires: 250258945Sroberto * 251258945Sroberto *\li 'timer' is a valid timer 252258945Sroberto * 253258945Sroberto *\li The same requirements that isc_timer_create() imposes on 'type', 254258945Sroberto * 'expires' and 'interval' apply. 255258945Sroberto * 256258945Sroberto * Ensures: 257258945Sroberto * 258258945Sroberto *\li An idle timeout will not be generated until at least Now + the 259258945Sroberto * timer's interval if 'timer' is a once timer with a non-zero 260258945Sroberto * interval. 261258945Sroberto * 262258945Sroberto * Returns: 263258945Sroberto * 264258945Sroberto *\li Success 265258945Sroberto *\li No memory 266258945Sroberto *\li Unexpected error 267258945Sroberto */ 268258945Sroberto 269258945Srobertoisc_result_t 270258945Srobertoisc_timer_touch(isc_timer_t *timer); 271258945Sroberto/*%< 272258945Sroberto * Set the last-touched time of 'timer' to the current time. 273258945Sroberto * 274258945Sroberto * Requires: 275258945Sroberto * 276258945Sroberto *\li 'timer' is a valid once timer. 277258945Sroberto * 278258945Sroberto * Ensures: 279258945Sroberto * 280258945Sroberto *\li An idle timeout will not be generated until at least Now + the 281258945Sroberto * timer's interval if 'timer' is a once timer with a non-zero 282258945Sroberto * interval. 283258945Sroberto * 284258945Sroberto * Returns: 285258945Sroberto * 286258945Sroberto *\li Success 287258945Sroberto *\li Unexpected error 288258945Sroberto */ 289258945Sroberto 290258945Srobertovoid 291258945Srobertoisc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp); 292258945Sroberto/*%< 293258945Sroberto * Attach *timerp to timer. 294258945Sroberto * 295258945Sroberto * Requires: 296258945Sroberto * 297258945Sroberto *\li 'timer' is a valid timer. 298258945Sroberto * 299258945Sroberto *\li 'timerp' points to a NULL timer. 300258945Sroberto * 301258945Sroberto * Ensures: 302258945Sroberto * 303258945Sroberto *\li *timerp is attached to timer. 304258945Sroberto */ 305258945Sroberto 306258945Srobertovoid 307258945Srobertoisc_timer_detach(isc_timer_t **timerp); 308258945Sroberto/*%< 309258945Sroberto * Detach *timerp from its timer. 310258945Sroberto * 311258945Sroberto * Requires: 312258945Sroberto * 313258945Sroberto *\li 'timerp' points to a valid timer. 314258945Sroberto * 315258945Sroberto * Ensures: 316258945Sroberto * 317258945Sroberto *\li *timerp is NULL. 318258945Sroberto * 319258945Sroberto *\li If '*timerp' is the last reference to the timer, 320258945Sroberto * then: 321258945Sroberto * 322258945Sroberto *\code 323258945Sroberto * The timer will be shutdown 324258945Sroberto * 325258945Sroberto * The timer will detach from its task 326258945Sroberto * 327258945Sroberto * All resources used by the timer have been freed 328258945Sroberto * 329258945Sroberto * Any events already posted by the timer will be purged. 330258945Sroberto * Therefore, if isc_timer_detach() is called in the context 331258945Sroberto * of the timer's task, it is guaranteed that no more 332258945Sroberto * timer event callbacks will run after the call. 333258945Sroberto *\endcode 334258945Sroberto */ 335258945Sroberto 336258945Srobertoisc_timertype_t 337258945Srobertoisc_timer_gettype(isc_timer_t *timer); 338258945Sroberto/*%< 339258945Sroberto * Return the timer type. 340258945Sroberto * 341258945Sroberto * Requires: 342258945Sroberto * 343258945Sroberto *\li 'timer' to be a valid timer. 344258945Sroberto */ 345258945Sroberto 346258945Srobertoisc_result_t 347280849Scyisc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, 348280849Scy isc_timermgr_t **managerp); 349280849Scy 350280849Scyisc_result_t 351258945Srobertoisc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp); 352258945Sroberto/*%< 353280849Scy * Create a timer manager. isc_timermgr_createinctx() also associates 354280849Scy * the new manager with the specified application context. 355258945Sroberto * 356258945Sroberto * Notes: 357258945Sroberto * 358258945Sroberto *\li All memory will be allocated in memory context 'mctx'. 359258945Sroberto * 360258945Sroberto * Requires: 361258945Sroberto * 362258945Sroberto *\li 'mctx' is a valid memory context. 363258945Sroberto * 364258945Sroberto *\li 'managerp' points to a NULL isc_timermgr_t. 365258945Sroberto * 366280849Scy *\li 'actx' is a valid application context (for createinctx()). 367280849Scy * 368258945Sroberto * Ensures: 369258945Sroberto * 370258945Sroberto *\li '*managerp' is a valid isc_timermgr_t. 371258945Sroberto * 372258945Sroberto * Returns: 373258945Sroberto * 374258945Sroberto *\li Success 375258945Sroberto *\li No memory 376258945Sroberto *\li Unexpected error 377258945Sroberto */ 378258945Sroberto 379258945Srobertovoid 380258945Srobertoisc_timermgr_destroy(isc_timermgr_t **managerp); 381258945Sroberto/*%< 382258945Sroberto * Destroy a timer manager. 383258945Sroberto * 384258945Sroberto * Notes: 385258945Sroberto * 386258945Sroberto *\li This routine blocks until there are no timers left in the manager, 387258945Sroberto * so if the caller holds any timer references using the manager, it 388258945Sroberto * must detach them before calling isc_timermgr_destroy() or it will 389258945Sroberto * block forever. 390258945Sroberto * 391258945Sroberto * Requires: 392258945Sroberto * 393258945Sroberto *\li '*managerp' is a valid isc_timermgr_t. 394258945Sroberto * 395258945Sroberto * Ensures: 396258945Sroberto * 397258945Sroberto *\li *managerp == NULL 398258945Sroberto * 399258945Sroberto *\li All resources used by the manager have been freed. 400258945Sroberto */ 401258945Sroberto 402258945Srobertovoid isc_timermgr_poke(isc_timermgr_t *m); 403258945Sroberto 404280849Scy#ifdef USE_TIMERIMPREGISTER 405280849Scy/*%< 406280849Scy * See isc_timermgr_create() above. 407280849Scy */ 408280849Scytypedef isc_result_t 409280849Scy(*isc_timermgrcreatefunc_t)(isc_mem_t *mctx, isc_timermgr_t **managerp); 410280849Scy 411280849Scyisc_result_t 412280849Scyisc__timer_register(void); 413280849Scy/*%< 414280849Scy * Register a new timer management implementation and add it to the list of 415280849Scy * supported implementations. This function must be called when a different 416280849Scy * event library is used than the one contained in the ISC library. 417280849Scy */ 418280849Scy 419280849Scyisc_result_t 420280849Scyisc_timer_register(isc_timermgrcreatefunc_t createfunc); 421280849Scy/*%< 422280849Scy * A short cut function that specifies the timer management module in the ISC 423280849Scy * library for isc_timer_register(). An application that uses the ISC library 424280849Scy * usually do not have to care about this function: it would call 425280849Scy * isc_lib_register(), which internally calls this function. 426280849Scy */ 427280849Scy#endif /* USE_TIMERIMPREGISTER */ 428280849Scy 429258945SrobertoISC_LANG_ENDDECLS 430258945Sroberto 431258945Sroberto#endif /* ISC_TIMER_H */ 432