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