2 * Copyright (C) 2004-2009, 2012 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1998-2002 Internet Software Consortium.
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.
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.
18 /* $Id: timer.h,v 1.43 2009/09/02 23:48:03 tbox Exp $ */
28 * \brief Provides timers which are event sources in the task system.
30 * Three types of timers are supported:
32 *\li 'ticker' timers generate a periodic tick event.
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
39 *\li 'limited' timers generate a periodic tick event until they reach
40 * their lifetime when they generate a life timeout event.
42 *\li 'inactive' timers generate no events.
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
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.
58 * No anticipated impact.
64 * No anticipated impact.
75 #include <isc/types.h>
76 #include <isc/event.h>
77 #include <isc/eventclass.h>
89 isc_timertype_ticker = 0, /*%< Ticker */
90 isc_timertype_once = 1, /*%< Once */
91 isc_timertype_limited = 2, /*%< Limited */
92 isc_timertype_inactive = 3 /*%< Inactive */
95 typedef struct isc_timerevent {
96 struct isc_event common;
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)
106 /*% Timer and timer manager methods */
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,
114 isc_taskaction_t action,
116 isc_timer_t **timerp);
117 } isc_timermgrmethods_t;
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;
130 * This structure is actually just the common prefix of a timer manager
131 * object implementation's version of an isc_timermgr_t.
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.
138 struct isc_timermgr {
139 unsigned int impmagic;
141 isc_timermgrmethods_t *methods;
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)
149 * This is the common prefix of a timer object. The same note as
150 * that for the timermgr structure applies.
153 unsigned int impmagic;
155 isc_timermethods_t *methods;
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)
163 *** Timer and Timer Manager Functions
165 *** Note: all Ensures conditions apply only if the result is success for
166 *** those functions which return an isc_result_t.
170 isc_timer_create(isc_timermgr_t *manager,
171 isc_timertype_t type,
172 const isc_time_t *expires,
173 const isc_interval_t *interval,
175 isc_taskaction_t action,
177 isc_timer_t **timerp);
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'.
186 *\li For ticker timers, the timer will generate a 'tick' event every
187 * 'interval' seconds. The value of 'expires' is ignored.
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.
195 *\li If 'expires' is NULL, the epoch will be used.
197 * If 'interval' is NULL, the zero interval will be used.
201 *\li 'manager' is a valid manager
203 *\li 'task' is a valid task
205 *\li 'action' is a valid action
207 *\li 'expires' points to a valid time, or is NULL.
209 *\li 'interval' points to a valid interval, or is NULL.
211 *\li type == isc_timertype_inactive ||
212 * ('expires' and 'interval' are not both 0)
214 *\li 'timerp' is a valid pointer, and *timerp == NULL
218 *\li '*timerp' is attached to the newly created timer
220 *\li The timer is attached to the task
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
230 *\li Unexpected error
234 isc_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);
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.
246 *\li If 'expires' is NULL, the epoch will be used.
248 *\li If 'interval' is NULL, the zero interval will be used.
252 *\li 'timer' is a valid timer
254 *\li The same requirements that isc_timer_create() imposes on 'type',
255 * 'expires' and 'interval' apply.
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
267 *\li Unexpected error
271 isc_timer_touch(isc_timer_t *timer);
273 * Set the last-touched time of 'timer' to the current time.
277 *\li 'timer' is a valid once timer.
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
288 *\li Unexpected error
292 isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp);
294 * Attach *timerp to timer.
298 *\li 'timer' is a valid timer.
300 *\li 'timerp' points to a NULL timer.
304 *\li *timerp is attached to timer.
308 isc_timer_detach(isc_timer_t **timerp);
310 * Detach *timerp from its timer.
314 *\li 'timerp' points to a valid timer.
318 *\li *timerp is NULL.
320 *\li If '*timerp' is the last reference to the timer,
324 * The timer will be shutdown
326 * The timer will detach from its task
328 * All resources used by the timer have been freed
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.
338 isc_timer_gettype(isc_timer_t *timer);
340 * Return the timer type.
344 *\li 'timer' to be a valid timer.
348 isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
349 isc_timermgr_t **managerp);
352 isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
354 * Create a timer manager. isc_timermgr_createinctx() also associates
355 * the new manager with the specified application context.
359 *\li All memory will be allocated in memory context 'mctx'.
363 *\li 'mctx' is a valid memory context.
365 *\li 'managerp' points to a NULL isc_timermgr_t.
367 *\li 'actx' is a valid application context (for createinctx()).
371 *\li '*managerp' is a valid isc_timermgr_t.
377 *\li Unexpected error
381 isc_timermgr_destroy(isc_timermgr_t **managerp);
383 * Destroy a timer manager.
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
394 *\li '*managerp' is a valid isc_timermgr_t.
398 *\li *managerp == NULL
400 *\li All resources used by the manager have been freed.
403 void isc_timermgr_poke(isc_timermgr_t *m);
405 #ifdef USE_TIMERIMPREGISTER
407 * See isc_timermgr_create() above.
410 (*isc_timermgrcreatefunc_t)(isc_mem_t *mctx, isc_timermgr_t **managerp);
413 isc__timer_register(void);
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.
421 isc_timer_register(isc_timermgrcreatefunc_t createfunc);
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.
428 #endif /* USE_TIMERIMPREGISTER */
432 #endif /* ISC_TIMER_H */