00001 /* 00002 * Copyright (C) 2004-2009, 2012-2014 Internet Systems Consortium, Inc. ("ISC") 00003 * Copyright (C) 1998-2002 Internet Software Consortium. 00004 * 00005 * Permission to use, copy, modify, and/or distribute this software for any 00006 * purpose with or without fee is hereby granted, provided that the above 00007 * copyright notice and this permission notice appear in all copies. 00008 * 00009 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 00010 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 00011 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 00012 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 00013 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 00014 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 00015 * PERFORMANCE OF THIS SOFTWARE. 00016 */ 00017 00018 /* $Id: timer.h,v 1.43 2009/09/02 23:48:03 tbox Exp $ */ 00019 00020 #ifndef ISC_TIMER_H 00021 #define ISC_TIMER_H 1 00022 00023 /***** 00024 ***** Module Info 00025 *****/ 00026 00027 /*! \file isc/timer.h 00028 * \brief Provides timers which are event sources in the task system. 00029 * 00030 * Three types of timers are supported: 00031 * 00032 *\li 'ticker' timers generate a periodic tick event. 00033 * 00034 *\li 'once' timers generate an idle timeout event if they are idle for too 00035 * long, and generate a life timeout event if their lifetime expires. 00036 * They are used to implement both (possibly expiring) idle timers and 00037 * 'one-shot' timers. 00038 * 00039 *\li 'limited' timers generate a periodic tick event until they reach 00040 * their lifetime when they generate a life timeout event. 00041 * 00042 *\li 'inactive' timers generate no events. 00043 * 00044 * Timers can change type. It is typical to create a timer as 00045 * an 'inactive' timer and then change it into a 'ticker' or 00046 * 'once' timer. 00047 * 00048 *\li MP: 00049 * The module ensures appropriate synchronization of data structures it 00050 * creates and manipulates. 00051 * Clients of this module must not be holding a timer's task's lock when 00052 * making a call that affects that timer. Failure to follow this rule 00053 * can result in deadlock. 00054 * The caller must ensure that isc_timermgr_destroy() is called only 00055 * once for a given manager. 00056 * 00057 * \li Reliability: 00058 * No anticipated impact. 00059 * 00060 * \li Resources: 00061 * TBS 00062 * 00063 * \li Security: 00064 * No anticipated impact. 00065 * 00066 * \li Standards: 00067 * None. 00068 */ 00069 00070 00071 /*** 00072 *** Imports 00073 ***/ 00074 00075 #include <isc/types.h> 00076 #include <isc/event.h> 00077 #include <isc/eventclass.h> 00078 #include <isc/lang.h> 00079 #include <isc/time.h> 00080 00081 ISC_LANG_BEGINDECLS 00082 00083 /*** 00084 *** Types 00085 ***/ 00086 00087 /*% Timer Type */ 00088 typedef enum { 00089 isc_timertype_undefined = -1, /*%< Undefined */ 00090 isc_timertype_ticker = 0, /*%< Ticker */ 00091 isc_timertype_once = 1, /*%< Once */ 00092 isc_timertype_limited = 2, /*%< Limited */ 00093 isc_timertype_inactive = 3 /*%< Inactive */ 00094 } isc_timertype_t; 00095 00096 typedef struct isc_timerevent { 00097 struct isc_event common; 00098 isc_time_t due; 00099 } isc_timerevent_t; 00100 00101 #define ISC_TIMEREVENT_FIRSTEVENT (ISC_EVENTCLASS_TIMER + 0) 00102 #define ISC_TIMEREVENT_TICK (ISC_EVENTCLASS_TIMER + 1) 00103 #define ISC_TIMEREVENT_IDLE (ISC_EVENTCLASS_TIMER + 2) 00104 #define ISC_TIMEREVENT_LIFE (ISC_EVENTCLASS_TIMER + 3) 00105 #define ISC_TIMEREVENT_LASTEVENT (ISC_EVENTCLASS_TIMER + 65535) 00106 00107 /*% Timer and timer manager methods */ 00108 typedef struct { 00109 void (*destroy)(isc_timermgr_t **managerp); 00110 isc_result_t (*timercreate)(isc_timermgr_t *manager, 00111 isc_timertype_t type, 00112 const isc_time_t *expires, 00113 const isc_interval_t *interval, 00114 isc_task_t *task, 00115 isc_taskaction_t action, 00116 void *arg, 00117 isc_timer_t **timerp); 00118 } isc_timermgrmethods_t; 00119 00120 typedef struct { 00121 void (*attach)(isc_timer_t *timer, isc_timer_t **timerp); 00122 void (*detach)(isc_timer_t **timerp); 00123 isc_result_t (*reset)(isc_timer_t *timer, isc_timertype_t type, 00124 const isc_time_t *expires, 00125 const isc_interval_t *interval, 00126 isc_boolean_t purge); 00127 isc_result_t (*touch)(isc_timer_t *timer); 00128 } isc_timermethods_t; 00129 00130 /*% 00131 * This structure is actually just the common prefix of a timer manager 00132 * object implementation's version of an isc_timermgr_t. 00133 * \brief 00134 * Direct use of this structure by clients is forbidden. timer implementations 00135 * may change the structure. 'magic' must be ISCAPI_TIMERMGR_MAGIC for any 00136 * of the isc_timer_ routines to work. timer implementations must maintain 00137 * all timer invariants. 00138 */ 00139 struct isc_timermgr { 00140 unsigned int impmagic; 00141 unsigned int magic; 00142 isc_timermgrmethods_t *methods; 00143 }; 00144 00145 #define ISCAPI_TIMERMGR_MAGIC ISC_MAGIC('A','t','m','g') 00146 #define ISCAPI_TIMERMGR_VALID(m) ((m) != NULL && \ 00147 (m)->magic == ISCAPI_TIMERMGR_MAGIC) 00148 00149 /*% 00150 * This is the common prefix of a timer object. The same note as 00151 * that for the timermgr structure applies. 00152 */ 00153 struct isc_timer { 00154 unsigned int impmagic; 00155 unsigned int magic; 00156 isc_timermethods_t *methods; 00157 }; 00158 00159 #define ISCAPI_TIMER_MAGIC ISC_MAGIC('A','t','m','r') 00160 #define ISCAPI_TIMER_VALID(s) ((s) != NULL && \ 00161 (s)->magic == ISCAPI_TIMER_MAGIC) 00162 00163 /*** 00164 *** Timer and Timer Manager Functions 00165 *** 00166 *** Note: all Ensures conditions apply only if the result is success for 00167 *** those functions which return an isc_result_t. 00168 ***/ 00169 00170 isc_result_t 00171 isc_timer_create(isc_timermgr_t *manager, 00172 isc_timertype_t type, 00173 const isc_time_t *expires, 00174 const isc_interval_t *interval, 00175 isc_task_t *task, 00176 isc_taskaction_t action, 00177 void *arg, 00178 isc_timer_t **timerp); 00179 /*%< 00180 * Create a new 'type' timer managed by 'manager'. The timers parameters 00181 * are specified by 'expires' and 'interval'. Events will be posted to 00182 * 'task' and when dispatched 'action' will be called with 'arg' as the 00183 * arg value. The new timer is returned in 'timerp'. 00184 * 00185 * Notes: 00186 * 00187 *\li For ticker timers, the timer will generate a 'tick' event every 00188 * 'interval' seconds. The value of 'expires' is ignored. 00189 * 00190 *\li For once timers, 'expires' specifies the time when a life timeout 00191 * event should be generated. If 'expires' is 0 (the epoch), then no life 00192 * timeout will be generated. 'interval' specifies how long the timer 00193 * can be idle before it generates an idle timeout. If 0, then no 00194 * idle timeout will be generated. 00195 * 00196 *\li If 'expires' is NULL, the epoch will be used. 00197 * 00198 * If 'interval' is NULL, the zero interval will be used. 00199 * 00200 * Requires: 00201 * 00202 *\li 'manager' is a valid manager 00203 * 00204 *\li 'task' is a valid task 00205 * 00206 *\li 'action' is a valid action 00207 * 00208 *\li 'expires' points to a valid time, or is NULL. 00209 * 00210 *\li 'interval' points to a valid interval, or is NULL. 00211 * 00212 *\li type == isc_timertype_inactive || 00213 * ('expires' and 'interval' are not both 0) 00214 * 00215 *\li 'timerp' is a valid pointer, and *timerp == NULL 00216 * 00217 * Ensures: 00218 * 00219 *\li '*timerp' is attached to the newly created timer 00220 * 00221 *\li The timer is attached to the task 00222 * 00223 *\li An idle timeout will not be generated until at least Now + the 00224 * timer's interval if 'timer' is a once timer with a non-zero 00225 * interval. 00226 * 00227 * Returns: 00228 * 00229 *\li Success 00230 *\li No memory 00231 *\li Unexpected error 00232 */ 00233 00234 isc_result_t 00235 isc_timer_reset(isc_timer_t *timer, 00236 isc_timertype_t type, 00237 const isc_time_t *expires, 00238 const isc_interval_t *interval, 00239 isc_boolean_t purge); 00240 /*%< 00241 * Change the timer's type, expires, and interval values to the given 00242 * values. If 'purge' is TRUE, any pending events from this timer 00243 * are purged from its task's event queue. 00244 * 00245 * Notes: 00246 * 00247 *\li If 'expires' is NULL, the epoch will be used. 00248 * 00249 *\li If 'interval' is NULL, the zero interval will be used. 00250 * 00251 * Requires: 00252 * 00253 *\li 'timer' is a valid timer 00254 * 00255 *\li The same requirements that isc_timer_create() imposes on 'type', 00256 * 'expires' and 'interval' apply. 00257 * 00258 * Ensures: 00259 * 00260 *\li An idle timeout will not be generated until at least Now + the 00261 * timer's interval if 'timer' is a once timer with a non-zero 00262 * interval. 00263 * 00264 * Returns: 00265 * 00266 *\li Success 00267 *\li No memory 00268 *\li Unexpected error 00269 */ 00270 00271 isc_result_t 00272 isc_timer_touch(isc_timer_t *timer); 00273 /*%< 00274 * Set the last-touched time of 'timer' to the current time. 00275 * 00276 * Requires: 00277 * 00278 *\li 'timer' is a valid once timer. 00279 * 00280 * Ensures: 00281 * 00282 *\li An idle timeout will not be generated until at least Now + the 00283 * timer's interval if 'timer' is a once timer with a non-zero 00284 * interval. 00285 * 00286 * Returns: 00287 * 00288 *\li Success 00289 *\li Unexpected error 00290 */ 00291 00292 void 00293 isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp); 00294 /*%< 00295 * Attach *timerp to timer. 00296 * 00297 * Requires: 00298 * 00299 *\li 'timer' is a valid timer. 00300 * 00301 *\li 'timerp' points to a NULL timer. 00302 * 00303 * Ensures: 00304 * 00305 *\li *timerp is attached to timer. 00306 */ 00307 00308 void 00309 isc_timer_detach(isc_timer_t **timerp); 00310 /*%< 00311 * Detach *timerp from its timer. 00312 * 00313 * Requires: 00314 * 00315 *\li 'timerp' points to a valid timer. 00316 * 00317 * Ensures: 00318 * 00319 *\li *timerp is NULL. 00320 * 00321 *\li If '*timerp' is the last reference to the timer, 00322 * then: 00323 * 00324 *\code 00325 * The timer will be shutdown 00326 * 00327 * The timer will detach from its task 00328 * 00329 * All resources used by the timer have been freed 00330 * 00331 * Any events already posted by the timer will be purged. 00332 * Therefore, if isc_timer_detach() is called in the context 00333 * of the timer's task, it is guaranteed that no more 00334 * timer event callbacks will run after the call. 00335 *\endcode 00336 */ 00337 00338 isc_timertype_t 00339 isc_timer_gettype(isc_timer_t *timer); 00340 /*%< 00341 * Return the timer type. 00342 * 00343 * Requires: 00344 * 00345 *\li 'timer' to be a valid timer. 00346 */ 00347 00348 isc_result_t 00349 isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, 00350 isc_timermgr_t **managerp); 00351 00352 isc_result_t 00353 isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp); 00354 /*%< 00355 * Create a timer manager. isc_timermgr_createinctx() also associates 00356 * the new manager with the specified application context. 00357 * 00358 * Notes: 00359 * 00360 *\li All memory will be allocated in memory context 'mctx'. 00361 * 00362 * Requires: 00363 * 00364 *\li 'mctx' is a valid memory context. 00365 * 00366 *\li 'managerp' points to a NULL isc_timermgr_t. 00367 * 00368 *\li 'actx' is a valid application context (for createinctx()). 00369 * 00370 * Ensures: 00371 * 00372 *\li '*managerp' is a valid isc_timermgr_t. 00373 * 00374 * Returns: 00375 * 00376 *\li Success 00377 *\li No memory 00378 *\li Unexpected error 00379 */ 00380 00381 void 00382 isc_timermgr_destroy(isc_timermgr_t **managerp); 00383 /*%< 00384 * Destroy a timer manager. 00385 * 00386 * Notes: 00387 * 00388 *\li This routine blocks until there are no timers left in the manager, 00389 * so if the caller holds any timer references using the manager, it 00390 * must detach them before calling isc_timermgr_destroy() or it will 00391 * block forever. 00392 * 00393 * Requires: 00394 * 00395 *\li '*managerp' is a valid isc_timermgr_t. 00396 * 00397 * Ensures: 00398 * 00399 *\li *managerp == NULL 00400 * 00401 *\li All resources used by the manager have been freed. 00402 */ 00403 00404 void isc_timermgr_poke(isc_timermgr_t *m); 00405 00406 /*%< 00407 * See isc_timermgr_create() above. 00408 */ 00409 typedef isc_result_t 00410 (*isc_timermgrcreatefunc_t)(isc_mem_t *mctx, isc_timermgr_t **managerp); 00411 00412 isc_result_t 00413 isc__timer_register(void); 00414 /*%< 00415 * Register a new timer management implementation and add it to the list of 00416 * supported implementations. This function must be called when a different 00417 * event library is used than the one contained in the ISC library. 00418 */ 00419 00420 isc_result_t 00421 isc_timer_register(isc_timermgrcreatefunc_t createfunc); 00422 /*%< 00423 * A short cut function that specifies the timer management module in the ISC 00424 * library for isc_timer_register(). An application that uses the ISC library 00425 * usually do not have to care about this function: it would call 00426 * isc_lib_register(), which internally calls this function. 00427 */ 00428 00429 ISC_LANG_ENDDECLS 00430 00431 #endif /* ISC_TIMER_H */