1/* 2 * Copyright (C) 2004-2009, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1998-2002 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: timer.h,v 1.43 2009/09/02 23:48:03 tbox Exp $ */ 19 20#ifndef ISC_TIMER_H 21#define ISC_TIMER_H 1 22 23/***** 24 ***** Module Info 25 *****/ 26 27/*! \file isc/timer.h 28 * \brief Provides timers which are event sources in the task system. 29 * 30 * Three types of timers are supported: 31 * 32 *\li 'ticker' timers generate a periodic tick event. 33 * 34 *\li 'once' timers generate an idle timeout event if they are idle for too 35 * long, and generate a life timeout event if their lifetime expires. 36 * They are used to implement both (possibly expiring) idle timers and 37 * 'one-shot' timers. 38 * 39 *\li 'limited' timers generate a periodic tick event until they reach 40 * their lifetime when they generate a life timeout event. 41 * 42 *\li 'inactive' timers generate no events. 43 * 44 * Timers can change type. It is typical to create a timer as 45 * an 'inactive' timer and then change it into a 'ticker' or 46 * 'once' timer. 47 * 48 *\li MP: 49 * The module ensures appropriate synchronization of data structures it 50 * creates and manipulates. 51 * Clients of this module must not be holding a timer's task's lock when 52 * making a call that affects that timer. Failure to follow this rule 53 * can result in deadlock. 54 * The caller must ensure that isc_timermgr_destroy() is called only 55 * once for a given manager. 56 * 57 * \li Reliability: 58 * No anticipated impact. 59 * 60 * \li Resources: 61 * TBS 62 * 63 * \li Security: 64 * No anticipated impact. 65 * 66 * \li Standards: 67 * None. 68 */ 69 70 71/*** 72 *** Imports 73 ***/ 74 75#include <isc/types.h> 76#include <isc/event.h> 77#include <isc/eventclass.h> 78#include <isc/lang.h> 79#include <isc/time.h> 80 81ISC_LANG_BEGINDECLS 82 83/*** 84 *** Types 85 ***/ 86 87/*% Timer Type */ 88typedef enum { 89 isc_timertype_ticker = 0, /*%< Ticker */ 90 isc_timertype_once = 1, /*%< Once */ 91 isc_timertype_limited = 2, /*%< Limited */ 92 isc_timertype_inactive = 3 /*%< Inactive */ 93} isc_timertype_t; 94 95typedef struct isc_timerevent { 96 struct isc_event common; 97 isc_time_t due; 98} isc_timerevent_t; 99 100#define ISC_TIMEREVENT_FIRSTEVENT (ISC_EVENTCLASS_TIMER + 0) 101#define ISC_TIMEREVENT_TICK (ISC_EVENTCLASS_TIMER + 1) 102#define ISC_TIMEREVENT_IDLE (ISC_EVENTCLASS_TIMER + 2) 103#define ISC_TIMEREVENT_LIFE (ISC_EVENTCLASS_TIMER + 3) 104#define ISC_TIMEREVENT_LASTEVENT (ISC_EVENTCLASS_TIMER + 65535) 105 106/*% Timer and timer manager methods */ 107typedef struct { 108 void (*destroy)(isc_timermgr_t **managerp); 109 isc_result_t (*timercreate)(isc_timermgr_t *manager, 110 isc_timertype_t type, 111 const isc_time_t *expires, 112 const isc_interval_t *interval, 113 isc_task_t *task, 114 isc_taskaction_t action, 115 const void *arg, 116 isc_timer_t **timerp); 117} isc_timermgrmethods_t; 118 119typedef struct { 120 void (*attach)(isc_timer_t *timer, isc_timer_t **timerp); 121 void (*detach)(isc_timer_t **timerp); 122 isc_result_t (*reset)(isc_timer_t *timer, isc_timertype_t type, 123 const isc_time_t *expires, 124 const isc_interval_t *interval, 125 isc_boolean_t purge); 126 isc_result_t (*touch)(isc_timer_t *timer); 127} isc_timermethods_t; 128 129/*% 130 * This structure is actually just the common prefix of a timer manager 131 * object implementation's version of an isc_timermgr_t. 132 * \brief 133 * Direct use of this structure by clients is forbidden. timer implementations 134 * may change the structure. 'magic' must be ISCAPI_TIMERMGR_MAGIC for any 135 * of the isc_timer_ routines to work. timer implementations must maintain 136 * all timer invariants. 137 */ 138struct isc_timermgr { 139 unsigned int impmagic; 140 unsigned int magic; 141 isc_timermgrmethods_t *methods; 142}; 143 144#define ISCAPI_TIMERMGR_MAGIC ISC_MAGIC('A','t','m','g') 145#define ISCAPI_TIMERMGR_VALID(m) ((m) != NULL && \ 146 (m)->magic == ISCAPI_TIMERMGR_MAGIC) 147 148/*% 149 * This is the common prefix of a timer object. The same note as 150 * that for the timermgr structure applies. 151 */ 152struct isc_timer { 153 unsigned int impmagic; 154 unsigned int magic; 155 isc_timermethods_t *methods; 156}; 157 158#define ISCAPI_TIMER_MAGIC ISC_MAGIC('A','t','m','r') 159#define ISCAPI_TIMER_VALID(s) ((s) != NULL && \ 160 (s)->magic == ISCAPI_TIMER_MAGIC) 161 162/*** 163 *** Timer and Timer Manager Functions 164 *** 165 *** Note: all Ensures conditions apply only if the result is success for 166 *** those functions which return an isc_result_t. 167 ***/ 168 169isc_result_t 170isc_timer_create(isc_timermgr_t *manager, 171 isc_timertype_t type, 172 const isc_time_t *expires, 173 const isc_interval_t *interval, 174 isc_task_t *task, 175 isc_taskaction_t action, 176 const void *arg, 177 isc_timer_t **timerp); 178/*%< 179 * Create a new 'type' timer managed by 'manager'. The timers parameters 180 * are specified by 'expires' and 'interval'. Events will be posted to 181 * 'task' and when dispatched 'action' will be called with 'arg' as the 182 * arg value. The new timer is returned in 'timerp'. 183 * 184 * Notes: 185 * 186 *\li For ticker timers, the timer will generate a 'tick' event every 187 * 'interval' seconds. The value of 'expires' is ignored. 188 * 189 *\li For once timers, 'expires' specifies the time when a life timeout 190 * event should be generated. If 'expires' is 0 (the epoch), then no life 191 * timeout will be generated. 'interval' specifies how long the timer 192 * can be idle before it generates an idle timeout. If 0, then no 193 * idle timeout will be generated. 194 * 195 *\li If 'expires' is NULL, the epoch will be used. 196 * 197 * If 'interval' is NULL, the zero interval will be used. 198 * 199 * Requires: 200 * 201 *\li 'manager' is a valid manager 202 * 203 *\li 'task' is a valid task 204 * 205 *\li 'action' is a valid action 206 * 207 *\li 'expires' points to a valid time, or is NULL. 208 * 209 *\li 'interval' points to a valid interval, or is NULL. 210 * 211 *\li type == isc_timertype_inactive || 212 * ('expires' and 'interval' are not both 0) 213 * 214 *\li 'timerp' is a valid pointer, and *timerp == NULL 215 * 216 * Ensures: 217 * 218 *\li '*timerp' is attached to the newly created timer 219 * 220 *\li The timer is attached to the task 221 * 222 *\li An idle timeout will not be generated until at least Now + the 223 * timer's interval if 'timer' is a once timer with a non-zero 224 * interval. 225 * 226 * Returns: 227 * 228 *\li Success 229 *\li No memory 230 *\li Unexpected error 231 */ 232 233isc_result_t 234isc_timer_reset(isc_timer_t *timer, 235 isc_timertype_t type, 236 const isc_time_t *expires, 237 const isc_interval_t *interval, 238 isc_boolean_t purge); 239/*%< 240 * Change the timer's type, expires, and interval values to the given 241 * values. If 'purge' is TRUE, any pending events from this timer 242 * are purged from its task's event queue. 243 * 244 * Notes: 245 * 246 *\li If 'expires' is NULL, the epoch will be used. 247 * 248 *\li If 'interval' is NULL, the zero interval will be used. 249 * 250 * Requires: 251 * 252 *\li 'timer' is a valid timer 253 * 254 *\li The same requirements that isc_timer_create() imposes on 'type', 255 * 'expires' and 'interval' apply. 256 * 257 * Ensures: 258 * 259 *\li An idle timeout will not be generated until at least Now + the 260 * timer's interval if 'timer' is a once timer with a non-zero 261 * interval. 262 * 263 * Returns: 264 * 265 *\li Success 266 *\li No memory 267 *\li Unexpected error 268 */ 269 270isc_result_t 271isc_timer_touch(isc_timer_t *timer); 272/*%< 273 * Set the last-touched time of 'timer' to the current time. 274 * 275 * Requires: 276 * 277 *\li 'timer' is a valid once timer. 278 * 279 * Ensures: 280 * 281 *\li An idle timeout will not be generated until at least Now + the 282 * timer's interval if 'timer' is a once timer with a non-zero 283 * interval. 284 * 285 * Returns: 286 * 287 *\li Success 288 *\li Unexpected error 289 */ 290 291void 292isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp); 293/*%< 294 * Attach *timerp to timer. 295 * 296 * Requires: 297 * 298 *\li 'timer' is a valid timer. 299 * 300 *\li 'timerp' points to a NULL timer. 301 * 302 * Ensures: 303 * 304 *\li *timerp is attached to timer. 305 */ 306 307void 308isc_timer_detach(isc_timer_t **timerp); 309/*%< 310 * Detach *timerp from its timer. 311 * 312 * Requires: 313 * 314 *\li 'timerp' points to a valid timer. 315 * 316 * Ensures: 317 * 318 *\li *timerp is NULL. 319 * 320 *\li If '*timerp' is the last reference to the timer, 321 * then: 322 * 323 *\code 324 * The timer will be shutdown 325 * 326 * The timer will detach from its task 327 * 328 * All resources used by the timer have been freed 329 * 330 * Any events already posted by the timer will be purged. 331 * Therefore, if isc_timer_detach() is called in the context 332 * of the timer's task, it is guaranteed that no more 333 * timer event callbacks will run after the call. 334 *\endcode 335 */ 336 337isc_timertype_t 338isc_timer_gettype(isc_timer_t *timer); 339/*%< 340 * Return the timer type. 341 * 342 * Requires: 343 * 344 *\li 'timer' to be a valid timer. 345 */ 346 347isc_result_t 348isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, 349 isc_timermgr_t **managerp); 350 351isc_result_t 352isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp); 353/*%< 354 * Create a timer manager. isc_timermgr_createinctx() also associates 355 * the new manager with the specified application context. 356 * 357 * Notes: 358 * 359 *\li All memory will be allocated in memory context 'mctx'. 360 * 361 * Requires: 362 * 363 *\li 'mctx' is a valid memory context. 364 * 365 *\li 'managerp' points to a NULL isc_timermgr_t. 366 * 367 *\li 'actx' is a valid application context (for createinctx()). 368 * 369 * Ensures: 370 * 371 *\li '*managerp' is a valid isc_timermgr_t. 372 * 373 * Returns: 374 * 375 *\li Success 376 *\li No memory 377 *\li Unexpected error 378 */ 379 380void 381isc_timermgr_destroy(isc_timermgr_t **managerp); 382/*%< 383 * Destroy a timer manager. 384 * 385 * Notes: 386 * 387 *\li This routine blocks until there are no timers left in the manager, 388 * so if the caller holds any timer references using the manager, it 389 * must detach them before calling isc_timermgr_destroy() or it will 390 * block forever. 391 * 392 * Requires: 393 * 394 *\li '*managerp' is a valid isc_timermgr_t. 395 * 396 * Ensures: 397 * 398 *\li *managerp == NULL 399 * 400 *\li All resources used by the manager have been freed. 401 */ 402 403void isc_timermgr_poke(isc_timermgr_t *m); 404 405#ifdef USE_TIMERIMPREGISTER 406/*%< 407 * See isc_timermgr_create() above. 408 */ 409typedef isc_result_t 410(*isc_timermgrcreatefunc_t)(isc_mem_t *mctx, isc_timermgr_t **managerp); 411 412isc_result_t 413isc__timer_register(void); 414/*%< 415 * Register a new timer management implementation and add it to the list of 416 * supported implementations. This function must be called when a different 417 * event library is used than the one contained in the ISC library. 418 */ 419 420isc_result_t 421isc_timer_register(isc_timermgrcreatefunc_t createfunc); 422/*%< 423 * A short cut function that specifies the timer management module in the ISC 424 * library for isc_timer_register(). An application that uses the ISC library 425 * usually do not have to care about this function: it would call 426 * isc_lib_register(), which internally calls this function. 427 */ 428#endif /* USE_TIMERIMPREGISTER */ 429 430ISC_LANG_ENDDECLS 431 432#endif /* ISC_TIMER_H */ 433