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