1 /*
2  * Copyright (C) 2004-2009  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 
81 ISC_LANG_BEGINDECLS
82 
83 /***
84  *** Types
85  ***/
86 
87 /*% Timer Type */
88 typedef 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 
95 typedef 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 */
107 typedef struct {
108 	void		(*destroy)(isc_timermgr_t **managerp);
109 	isc_result_t	(*timercreate)(isc_timermgr_t *manager,
110 				       isc_timertype_t type,
111 				       isc_time_t *expires,
112 				       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 
119 typedef 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 				 isc_time_t *expires, isc_interval_t *interval,
124 				 isc_boolean_t purge);
125 	isc_result_t	(*touch)(isc_timer_t *timer);
126 } isc_timermethods_t;
127 
128 /*%
129  * This structure is actually just the common prefix of a timer manager
130  * object implementation's version of an isc_timermgr_t.
131  * \brief
132  * Direct use of this structure by clients is forbidden.  timer implementations
133  * may change the structure.  'magic' must be ISCAPI_TIMERMGR_MAGIC for any
134  * of the isc_timer_ routines to work.  timer implementations must maintain
135  * all timer invariants.
136  */
137 struct isc_timermgr {
138 	unsigned int		impmagic;
139 	unsigned int		magic;
140 	isc_timermgrmethods_t	*methods;
141 };
142 
143 #define ISCAPI_TIMERMGR_MAGIC		ISC_MAGIC('A','t','m','g')
144 #define ISCAPI_TIMERMGR_VALID(m)	((m) != NULL && \
145 					 (m)->magic == ISCAPI_TIMERMGR_MAGIC)
146 
147 /*%
148  * This is the common prefix of a timer object.  The same note as
149  * that for the timermgr structure applies.
150  */
151 struct isc_timer {
152 	unsigned int		impmagic;
153 	unsigned int		magic;
154 	isc_timermethods_t	*methods;
155 };
156 
157 #define ISCAPI_TIMER_MAGIC	ISC_MAGIC('A','t','m','r')
158 #define ISCAPI_TIMER_VALID(s)	((s) != NULL && \
159 				 (s)->magic == ISCAPI_TIMER_MAGIC)
160 
161 /***
162  *** Timer and Timer Manager Functions
163  ***
164  *** Note: all Ensures conditions apply only if the result is success for
165  *** those functions which return an isc_result_t.
166  ***/
167 
168 isc_result_t
169 isc_timer_create(isc_timermgr_t *manager,
170 		 isc_timertype_t type,
171 		 isc_time_t *expires,
172 		 isc_interval_t *interval,
173 		 isc_task_t *task,
174 		 isc_taskaction_t action,
175 		 const void *arg,
176 		 isc_timer_t **timerp);
177 /*%<
178  * Create a new 'type' timer managed by 'manager'.  The timers parameters
179  * are specified by 'expires' and 'interval'.  Events will be posted to
180  * 'task' and when dispatched 'action' will be called with 'arg' as the
181  * arg value.  The new timer is returned in 'timerp'.
182  *
183  * Notes:
184  *
185  *\li	For ticker timers, the timer will generate a 'tick' event every
186  *	'interval' seconds.  The value of 'expires' is ignored.
187  *
188  *\li	For once timers, 'expires' specifies the time when a life timeout
189  *	event should be generated.  If 'expires' is 0 (the epoch), then no life
190  *	timeout will be generated.  'interval' specifies how long the timer
191  *	can be idle before it generates an idle timeout.  If 0, then no
192  *	idle timeout will be generated.
193  *
194  *\li	If 'expires' is NULL, the epoch will be used.
195  *
196  *	If 'interval' is NULL, the zero interval will be used.
197  *
198  * Requires:
199  *
200  *\li	'manager' is a valid manager
201  *
202  *\li	'task' is a valid task
203  *
204  *\li	'action' is a valid action
205  *
206  *\li	'expires' points to a valid time, or is NULL.
207  *
208  *\li	'interval' points to a valid interval, or is NULL.
209  *
210  *\li	type == isc_timertype_inactive ||
211  *	('expires' and 'interval' are not both 0)
212  *
213  *\li	'timerp' is a valid pointer, and *timerp == NULL
214  *
215  * Ensures:
216  *
217  *\li	'*timerp' is attached to the newly created timer
218  *
219  *\li	The timer is attached to the task
220  *
221  *\li	An idle timeout will not be generated until at least Now + the
222  *	timer's interval if 'timer' is a once timer with a non-zero
223  *	interval.
224  *
225  * Returns:
226  *
227  *\li	Success
228  *\li	No memory
229  *\li	Unexpected error
230  */
231 
232 isc_result_t
233 isc_timer_reset(isc_timer_t *timer,
234 		isc_timertype_t type,
235 		isc_time_t *expires,
236 		isc_interval_t *interval,
237 		isc_boolean_t purge);
238 /*%<
239  * Change the timer's type, expires, and interval values to the given
240  * values.  If 'purge' is TRUE, any pending events from this timer
241  * are purged from its task's event queue.
242  *
243  * Notes:
244  *
245  *\li	If 'expires' is NULL, the epoch will be used.
246  *
247  *\li	If 'interval' is NULL, the zero interval will be used.
248  *
249  * Requires:
250  *
251  *\li	'timer' is a valid timer
252  *
253  *\li	The same requirements that isc_timer_create() imposes on 'type',
254  *	'expires' and 'interval' apply.
255  *
256  * Ensures:
257  *
258  *\li	An idle timeout will not be generated until at least Now + the
259  *	timer's interval if 'timer' is a once timer with a non-zero
260  *	interval.
261  *
262  * Returns:
263  *
264  *\li	Success
265  *\li	No memory
266  *\li	Unexpected error
267  */
268 
269 isc_result_t
270 isc_timer_touch(isc_timer_t *timer);
271 /*%<
272  * Set the last-touched time of 'timer' to the current time.
273  *
274  * Requires:
275  *
276  *\li	'timer' is a valid once timer.
277  *
278  * Ensures:
279  *
280  *\li	An idle timeout will not be generated until at least Now + the
281  *	timer's interval if 'timer' is a once timer with a non-zero
282  *	interval.
283  *
284  * Returns:
285  *
286  *\li	Success
287  *\li	Unexpected error
288  */
289 
290 void
291 isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp);
292 /*%<
293  * Attach *timerp to timer.
294  *
295  * Requires:
296  *
297  *\li	'timer' is a valid timer.
298  *
299  *\li	'timerp' points to a NULL timer.
300  *
301  * Ensures:
302  *
303  *\li	*timerp is attached to timer.
304  */
305 
306 void
307 isc_timer_detach(isc_timer_t **timerp);
308 /*%<
309  * Detach *timerp from its timer.
310  *
311  * Requires:
312  *
313  *\li	'timerp' points to a valid timer.
314  *
315  * Ensures:
316  *
317  *\li	*timerp is NULL.
318  *
319  *\li	If '*timerp' is the last reference to the timer,
320  *	then:
321  *
322  *\code
323  *		The timer will be shutdown
324  *
325  *		The timer will detach from its task
326  *
327  *		All resources used by the timer have been freed
328  *
329  *		Any events already posted by the timer will be purged.
330  *		Therefore, if isc_timer_detach() is called in the context
331  *		of the timer's task, it is guaranteed that no more
332  *		timer event callbacks will run after the call.
333  *\endcode
334  */
335 
336 isc_timertype_t
337 isc_timer_gettype(isc_timer_t *timer);
338 /*%<
339  * Return the timer type.
340  *
341  * Requires:
342  *
343  *\li	'timer' to be a valid timer.
344  */
345 
346 isc_result_t
347 isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
348 			 isc_timermgr_t **managerp);
349 
350 isc_result_t
351 isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
352 /*%<
353  * Create a timer manager.  isc_timermgr_createinctx() also associates
354  * the new manager with the specified application context.
355  *
356  * Notes:
357  *
358  *\li	All memory will be allocated in memory context 'mctx'.
359  *
360  * Requires:
361  *
362  *\li	'mctx' is a valid memory context.
363  *
364  *\li	'managerp' points to a NULL isc_timermgr_t.
365  *
366  *\li	'actx' is a valid application context (for createinctx()).
367  *
368  * Ensures:
369  *
370  *\li	'*managerp' is a valid isc_timermgr_t.
371  *
372  * Returns:
373  *
374  *\li	Success
375  *\li	No memory
376  *\li	Unexpected error
377  */
378 
379 void
380 isc_timermgr_destroy(isc_timermgr_t **managerp);
381 /*%<
382  * Destroy a timer manager.
383  *
384  * Notes:
385  *
386  *\li	This routine blocks until there are no timers left in the manager,
387  *	so if the caller holds any timer references using the manager, it
388  *	must detach them before calling isc_timermgr_destroy() or it will
389  *	block forever.
390  *
391  * Requires:
392  *
393  *\li	'*managerp' is a valid isc_timermgr_t.
394  *
395  * Ensures:
396  *
397  *\li	*managerp == NULL
398  *
399  *\li	All resources used by the manager have been freed.
400  */
401 
402 void isc_timermgr_poke(isc_timermgr_t *m);
403 
404 #ifdef USE_TIMERIMPREGISTER
405 /*%<
406  * See isc_timermgr_create() above.
407  */
408 typedef isc_result_t
409 (*isc_timermgrcreatefunc_t)(isc_mem_t *mctx, isc_timermgr_t **managerp);
410 
411 isc_result_t
412 isc__timer_register(void);
413 /*%<
414  * Register a new timer management implementation and add it to the list of
415  * supported implementations.  This function must be called when a different
416  * event library is used than the one contained in the ISC library.
417  */
418 
419 isc_result_t
420 isc_timer_register(isc_timermgrcreatefunc_t createfunc);
421 /*%<
422  * A short cut function that specifies the timer management module in the ISC
423  * library for isc_timer_register().  An application that uses the ISC library
424  * usually do not have to care about this function: it would call
425  * isc_lib_register(), which internally calls this function.
426  */
427 #endif /* USE_TIMERIMPREGISTER */
428 
429 ISC_LANG_ENDDECLS
430 
431 #endif /* ISC_TIMER_H */
432