1d54cfbdroberto/*
2047f369cy * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
3d54cfbdroberto * Copyright (C) 1998-2002  Internet Software Consortium.
4d54cfbdroberto *
5d54cfbdroberto * Permission to use, copy, modify, and/or distribute this software for any
6d54cfbdroberto * purpose with or without fee is hereby granted, provided that the above
7d54cfbdroberto * copyright notice and this permission notice appear in all copies.
8d54cfbdroberto *
9d54cfbdroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10d54cfbdroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11d54cfbdroberto * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12d54cfbdroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13d54cfbdroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14d54cfbdroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15d54cfbdroberto * PERFORMANCE OF THIS SOFTWARE.
16d54cfbdroberto */
17d54cfbdroberto
18047f369cy/* $Id: timer.h,v 1.43 2009/09/02 23:48:03 tbox Exp $ */
19d54cfbdroberto
20d54cfbdroberto#ifndef ISC_TIMER_H
21d54cfbdroberto#define ISC_TIMER_H 1
22d54cfbdroberto
23d54cfbdroberto/*****
24d54cfbdroberto ***** Module Info
25d54cfbdroberto *****/
26d54cfbdroberto
27d54cfbdroberto/*! \file isc/timer.h
28d54cfbdroberto * \brief Provides timers which are event sources in the task system.
29d54cfbdroberto *
30d54cfbdroberto * Three types of timers are supported:
31d54cfbdroberto *
32d54cfbdroberto *\li	'ticker' timers generate a periodic tick event.
33d54cfbdroberto *
34d54cfbdroberto *\li	'once' timers generate an idle timeout event if they are idle for too
35d54cfbdroberto *	long, and generate a life timeout event if their lifetime expires.
36d54cfbdroberto *	They are used to implement both (possibly expiring) idle timers and
37d54cfbdroberto *	'one-shot' timers.
38d54cfbdroberto *
39d54cfbdroberto *\li	'limited' timers generate a periodic tick event until they reach
40d54cfbdroberto *	their lifetime when they generate a life timeout event.
41d54cfbdroberto *
42d54cfbdroberto *\li	'inactive' timers generate no events.
43d54cfbdroberto *
44d54cfbdroberto * Timers can change type.  It is typical to create a timer as
45d54cfbdroberto * an 'inactive' timer and then change it into a 'ticker' or
46d54cfbdroberto * 'once' timer.
47d54cfbdroberto *
48d54cfbdroberto *\li MP:
49d54cfbdroberto *	The module ensures appropriate synchronization of data structures it
50d54cfbdroberto *	creates and manipulates.
51d54cfbdroberto *	Clients of this module must not be holding a timer's task's lock when
52d54cfbdroberto *	making a call that affects that timer.  Failure to follow this rule
53d54cfbdroberto *	can result in deadlock.
54d54cfbdroberto *	The caller must ensure that isc_timermgr_destroy() is called only
55d54cfbdroberto *	once for a given manager.
56d54cfbdroberto *
57d54cfbdroberto * \li Reliability:
58d54cfbdroberto *	No anticipated impact.
59d54cfbdroberto *
60d54cfbdroberto * \li Resources:
61d54cfbdroberto *	TBS
62d54cfbdroberto *
63d54cfbdroberto * \li Security:
64d54cfbdroberto *	No anticipated impact.
65d54cfbdroberto *
66d54cfbdroberto * \li Standards:
67d54cfbdroberto *	None.
68d54cfbdroberto */
69d54cfbdroberto
70d54cfbdroberto
71d54cfbdroberto/***
72d54cfbdroberto *** Imports
73d54cfbdroberto ***/
74d54cfbdroberto
75d54cfbdroberto#include <isc/types.h>
76d54cfbdroberto#include <isc/event.h>
77d54cfbdroberto#include <isc/eventclass.h>
78d54cfbdroberto#include <isc/lang.h>
79d54cfbdroberto#include <isc/time.h>
80d54cfbdroberto
81d54cfbdrobertoISC_LANG_BEGINDECLS
82d54cfbdroberto
83d54cfbdroberto/***
84d54cfbdroberto *** Types
85d54cfbdroberto ***/
86d54cfbdroberto
87d54cfbdroberto/*% Timer Type */
88d54cfbdrobertotypedef enum {
89d54cfbdroberto	isc_timertype_ticker = 0, 	/*%< Ticker */
90d54cfbdroberto	isc_timertype_once = 1, 	/*%< Once */
91d54cfbdroberto	isc_timertype_limited = 2, 	/*%< Limited */
92d54cfbdroberto	isc_timertype_inactive = 3 	/*%< Inactive */
93d54cfbdroberto} isc_timertype_t;
94d54cfbdroberto
95d54cfbdrobertotypedef struct isc_timerevent {
96d54cfbdroberto	struct isc_event	common;
97d54cfbdroberto	isc_time_t		due;
98d54cfbdroberto} isc_timerevent_t;
99d54cfbdroberto
100d54cfbdroberto#define ISC_TIMEREVENT_FIRSTEVENT	(ISC_EVENTCLASS_TIMER + 0)
101d54cfbdroberto#define ISC_TIMEREVENT_TICK		(ISC_EVENTCLASS_TIMER + 1)
102d54cfbdroberto#define ISC_TIMEREVENT_IDLE		(ISC_EVENTCLASS_TIMER + 2)
103d54cfbdroberto#define ISC_TIMEREVENT_LIFE		(ISC_EVENTCLASS_TIMER + 3)
104d54cfbdroberto#define ISC_TIMEREVENT_LASTEVENT	(ISC_EVENTCLASS_TIMER + 65535)
105d54cfbdroberto
106047f369cy/*% Timer and timer manager methods */
107047f369cytypedef struct {
108047f369cy	void		(*destroy)(isc_timermgr_t **managerp);
109047f369cy	isc_result_t	(*timercreate)(isc_timermgr_t *manager,
110047f369cy				       isc_timertype_t type,
111047f369cy				       isc_time_t *expires,
112047f369cy				       isc_interval_t *interval,
113047f369cy				       isc_task_t *task,
114047f369cy				       isc_taskaction_t action,
115047f369cy				       const void *arg,
116047f369cy				       isc_timer_t **timerp);
117047f369cy} isc_timermgrmethods_t;
118047f369cy
119047f369cytypedef struct {
120047f369cy	void		(*attach)(isc_timer_t *timer, isc_timer_t **timerp);
121047f369cy	void		(*detach)(isc_timer_t **timerp);
122047f369cy	isc_result_t	(*reset)(isc_timer_t *timer, isc_timertype_t type,
123047f369cy				 isc_time_t *expires, isc_interval_t *interval,
124047f369cy				 isc_boolean_t purge);
125047f369cy	isc_result_t	(*touch)(isc_timer_t *timer);
126047f369cy} isc_timermethods_t;
127047f369cy
128047f369cy/*%
129047f369cy * This structure is actually just the common prefix of a timer manager
130047f369cy * object implementation's version of an isc_timermgr_t.
131047f369cy * \brief
132047f369cy * Direct use of this structure by clients is forbidden.  timer implementations
133047f369cy * may change the structure.  'magic' must be ISCAPI_TIMERMGR_MAGIC for any
134047f369cy * of the isc_timer_ routines to work.  timer implementations must maintain
135047f369cy * all timer invariants.
136047f369cy */
137047f369cystruct isc_timermgr {
138047f369cy	unsigned int		impmagic;
139047f369cy	unsigned int		magic;
140047f369cy	isc_timermgrmethods_t	*methods;
141047f369cy};
142047f369cy
143047f369cy#define ISCAPI_TIMERMGR_MAGIC		ISC_MAGIC('A','t','m','g')
144047f369cy#define ISCAPI_TIMERMGR_VALID(m)	((m) != NULL && \
145047f369cy					 (m)->magic == ISCAPI_TIMERMGR_MAGIC)
146047f369cy
147047f369cy/*%
148047f369cy * This is the common prefix of a timer object.  The same note as
149047f369cy * that for the timermgr structure applies.
150047f369cy */
151047f369cystruct isc_timer {
152047f369cy	unsigned int		impmagic;
153047f369cy	unsigned int		magic;
154047f369cy	isc_timermethods_t	*methods;
155047f369cy};
156047f369cy
157047f369cy#define ISCAPI_TIMER_MAGIC	ISC_MAGIC('A','t','m','r')
158047f369cy#define ISCAPI_TIMER_VALID(s)	((s) != NULL && \
159047f369cy				 (s)->magic == ISCAPI_TIMER_MAGIC)
160047f369cy
161d54cfbdroberto/***
162d54cfbdroberto *** Timer and Timer Manager Functions
163d54cfbdroberto ***
164d54cfbdroberto *** Note: all Ensures conditions apply only if the result is success for
165d54cfbdroberto *** those functions which return an isc_result_t.
166d54cfbdroberto ***/
167d54cfbdroberto
168d54cfbdrobertoisc_result_t
169d54cfbdrobertoisc_timer_create(isc_timermgr_t *manager,
170d54cfbdroberto		 isc_timertype_t type,
171d54cfbdroberto		 isc_time_t *expires,
172d54cfbdroberto		 isc_interval_t *interval,
173d54cfbdroberto		 isc_task_t *task,
174d54cfbdroberto		 isc_taskaction_t action,
175d54cfbdroberto		 const void *arg,
176d54cfbdroberto		 isc_timer_t **timerp);
177d54cfbdroberto/*%<
178d54cfbdroberto * Create a new 'type' timer managed by 'manager'.  The timers parameters
179d54cfbdroberto * are specified by 'expires' and 'interval'.  Events will be posted to
180d54cfbdroberto * 'task' and when dispatched 'action' will be called with 'arg' as the
181d54cfbdroberto * arg value.  The new timer is returned in 'timerp'.
182d54cfbdroberto *
183d54cfbdroberto * Notes:
184d54cfbdroberto *
185d54cfbdroberto *\li	For ticker timers, the timer will generate a 'tick' event every
186d54cfbdroberto *	'interval' seconds.  The value of 'expires' is ignored.
187d54cfbdroberto *
188d54cfbdroberto *\li	For once timers, 'expires' specifies the time when a life timeout
189d54cfbdroberto *	event should be generated.  If 'expires' is 0 (the epoch), then no life
190d54cfbdroberto *	timeout will be generated.  'interval' specifies how long the timer
191d54cfbdroberto *	can be idle before it generates an idle timeout.  If 0, then no
192d54cfbdroberto *	idle timeout will be generated.
193d54cfbdroberto *
194d54cfbdroberto *\li	If 'expires' is NULL, the epoch will be used.
195d54cfbdroberto *
196d54cfbdroberto *	If 'interval' is NULL, the zero interval will be used.
197d54cfbdroberto *
198d54cfbdroberto * Requires:
199d54cfbdroberto *
200d54cfbdroberto *\li	'manager' is a valid manager
201d54cfbdroberto *
202d54cfbdroberto *\li	'task' is a valid task
203d54cfbdroberto *
204d54cfbdroberto *\li	'action' is a valid action
205d54cfbdroberto *
206d54cfbdroberto *\li	'expires' points to a valid time, or is NULL.
207d54cfbdroberto *
208d54cfbdroberto *\li	'interval' points to a valid interval, or is NULL.
209d54cfbdroberto *
210d54cfbdroberto *\li	type == isc_timertype_inactive ||
211d54cfbdroberto *	('expires' and 'interval' are not both 0)
212d54cfbdroberto *
213d54cfbdroberto *\li	'timerp' is a valid pointer, and *timerp == NULL
214d54cfbdroberto *
215d54cfbdroberto * Ensures:
216d54cfbdroberto *
217d54cfbdroberto *\li	'*timerp' is attached to the newly created timer
218d54cfbdroberto *
219d54cfbdroberto *\li	The timer is attached to the task
220d54cfbdroberto *
221d54cfbdroberto *\li	An idle timeout will not be generated until at least Now + the
222d54cfbdroberto *	timer's interval if 'timer' is a once timer with a non-zero
223d54cfbdroberto *	interval.
224d54cfbdroberto *
225d54cfbdroberto * Returns:
226d54cfbdroberto *
227d54cfbdroberto *\li	Success
228d54cfbdroberto *\li	No memory
229d54cfbdroberto *\li	Unexpected error
230d54cfbdroberto */
231d54cfbdroberto
232d54cfbdrobertoisc_result_t
233d54cfbdrobertoisc_timer_reset(isc_timer_t *timer,
234d54cfbdroberto		isc_timertype_t type,
235d54cfbdroberto		isc_time_t *expires,
236d54cfbdroberto		isc_interval_t *interval,
237d54cfbdroberto		isc_boolean_t purge);
238d54cfbdroberto/*%<
239d54cfbdroberto * Change the timer's type, expires, and interval values to the given
240d54cfbdroberto * values.  If 'purge' is TRUE, any pending events from this timer
241d54cfbdroberto * are purged from its task's event queue.
242d54cfbdroberto *
243d54cfbdroberto * Notes:
244d54cfbdroberto *
245d54cfbdroberto *\li	If 'expires' is NULL, the epoch will be used.
246d54cfbdroberto *
247d54cfbdroberto *\li	If 'interval' is NULL, the zero interval will be used.
248d54cfbdroberto *
249d54cfbdroberto * Requires:
250d54cfbdroberto *
251d54cfbdroberto *\li	'timer' is a valid timer
252d54cfbdroberto *
253d54cfbdroberto *\li	The same requirements that isc_timer_create() imposes on 'type',
254d54cfbdroberto *	'expires' and 'interval' apply.
255d54cfbdroberto *
256d54cfbdroberto * Ensures:
257d54cfbdroberto *
258d54cfbdroberto *\li	An idle timeout will not be generated until at least Now + the
259d54cfbdroberto *	timer's interval if 'timer' is a once timer with a non-zero
260d54cfbdroberto *	interval.
261d54cfbdroberto *
262d54cfbdroberto * Returns:
263d54cfbdroberto *
264d54cfbdroberto *\li	Success
265d54cfbdroberto *\li	No memory
266d54cfbdroberto *\li	Unexpected error
267d54cfbdroberto */
268d54cfbdroberto
269d54cfbdrobertoisc_result_t
270d54cfbdrobertoisc_timer_touch(isc_timer_t *timer);
271d54cfbdroberto/*%<
272d54cfbdroberto * Set the last-touched time of 'timer' to the current time.
273d54cfbdroberto *
274d54cfbdroberto * Requires:
275d54cfbdroberto *
276d54cfbdroberto *\li	'timer' is a valid once timer.
277d54cfbdroberto *
278d54cfbdroberto * Ensures:
279d54cfbdroberto *
280d54cfbdroberto *\li	An idle timeout will not be generated until at least Now + the
281d54cfbdroberto *	timer's interval if 'timer' is a once timer with a non-zero
282d54cfbdroberto *	interval.
283d54cfbdroberto *
284d54cfbdroberto * Returns:
285d54cfbdroberto *
286d54cfbdroberto *\li	Success
287d54cfbdroberto *\li	Unexpected error
288d54cfbdroberto */
289d54cfbdroberto
290d54cfbdrobertovoid
291d54cfbdrobertoisc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp);
292d54cfbdroberto/*%<
293d54cfbdroberto * Attach *timerp to timer.
294d54cfbdroberto *
295d54cfbdroberto * Requires:
296d54cfbdroberto *
297d54cfbdroberto *\li	'timer' is a valid timer.
298d54cfbdroberto *
299d54cfbdroberto *\li	'timerp' points to a NULL timer.
300d54cfbdroberto *
301d54cfbdroberto * Ensures:
302d54cfbdroberto *
303d54cfbdroberto *\li	*timerp is attached to timer.
304d54cfbdroberto */
305d54cfbdroberto
306d54cfbdrobertovoid
307d54cfbdrobertoisc_timer_detach(isc_timer_t **timerp);
308d54cfbdroberto/*%<
309d54cfbdroberto * Detach *timerp from its timer.
310d54cfbdroberto *
311d54cfbdroberto * Requires:
312d54cfbdroberto *
313d54cfbdroberto *\li	'timerp' points to a valid timer.
314d54cfbdroberto *
315d54cfbdroberto * Ensures:
316d54cfbdroberto *
317d54cfbdroberto *\li	*timerp is NULL.
318d54cfbdroberto *
319d54cfbdroberto *\li	If '*timerp' is the last reference to the timer,
320d54cfbdroberto *	then:
321d54cfbdroberto *
322d54cfbdroberto *\code
323d54cfbdroberto *		The timer will be shutdown
324d54cfbdroberto *
325d54cfbdroberto *		The timer will detach from its task
326d54cfbdroberto *
327d54cfbdroberto *		All resources used by the timer have been freed
328d54cfbdroberto *
329d54cfbdroberto *		Any events already posted by the timer will be purged.
330d54cfbdroberto *		Therefore, if isc_timer_detach() is called in the context
331d54cfbdroberto *		of the timer's task, it is guaranteed that no more
332d54cfbdroberto *		timer event callbacks will run after the call.
333d54cfbdroberto *\endcode
334d54cfbdroberto */
335d54cfbdroberto
336d54cfbdrobertoisc_timertype_t
337d54cfbdrobertoisc_timer_gettype(isc_timer_t *timer);
338d54cfbdroberto/*%<
339d54cfbdroberto * Return the timer type.
340d54cfbdroberto *
341d54cfbdroberto * Requires:
342d54cfbdroberto *
343d54cfbdroberto *\li	'timer' to be a valid timer.
344d54cfbdroberto */
345d54cfbdroberto
346d54cfbdrobertoisc_result_t
347047f369cyisc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
348047f369cy			 isc_timermgr_t **managerp);
349047f369cy
350047f369cyisc_result_t
351d54cfbdrobertoisc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
352d54cfbdroberto/*%<
353047f369cy * Create a timer manager.  isc_timermgr_createinctx() also associates
354047f369cy * the new manager with the specified application context.
355d54cfbdroberto *
356d54cfbdroberto * Notes:
357d54cfbdroberto *
358d54cfbdroberto *\li	All memory will be allocated in memory context 'mctx'.
359d54cfbdroberto *
360d54cfbdroberto * Requires:
361d54cfbdroberto *
362d54cfbdroberto *\li	'mctx' is a valid memory context.
363d54cfbdroberto *
364d54cfbdroberto *\li	'managerp' points to a NULL isc_timermgr_t.
365d54cfbdroberto *
366047f369cy *\li	'actx' is a valid application context (for createinctx()).
367047f369cy *
368d54cfbdroberto * Ensures:
369d54cfbdroberto *
370d54cfbdroberto *\li	'*managerp' is a valid isc_timermgr_t.
371d54cfbdroberto *
372d54cfbdroberto * Returns:
373d54cfbdroberto *
374d54cfbdroberto *\li	Success
375d54cfbdroberto *\li	No memory
376d54cfbdroberto *\li	Unexpected error
377d54cfbdroberto */
378d54cfbdroberto
379d54cfbdrobertovoid
380d54cfbdrobertoisc_timermgr_destroy(isc_timermgr_t **managerp);
381d54cfbdroberto/*%<
382d54cfbdroberto * Destroy a timer manager.
383d54cfbdroberto *
384d54cfbdroberto * Notes:
385d54cfbdroberto *
386d54cfbdroberto *\li	This routine blocks until there are no timers left in the manager,
387d54cfbdroberto *	so if the caller holds any timer references using the manager, it
388d54cfbdroberto *	must detach them before calling isc_timermgr_destroy() or it will
389d54cfbdroberto *	block forever.
390d54cfbdroberto *
391d54cfbdroberto * Requires:
392d54cfbdroberto *
393d54cfbdroberto *\li	'*managerp' is a valid isc_timermgr_t.
394d54cfbdroberto *
395d54cfbdroberto * Ensures:
396d54cfbdroberto *
397d54cfbdroberto *\li	*managerp == NULL
398d54cfbdroberto *
399d54cfbdroberto *\li	All resources used by the manager have been freed.
400d54cfbdroberto */
401d54cfbdroberto
402d54cfbdrobertovoid isc_timermgr_poke(isc_timermgr_t *m);
403d54cfbdroberto
404047f369cy#ifdef USE_TIMERIMPREGISTER
405047f369cy/*%<
406047f369cy * See isc_timermgr_create() above.
407047f369cy */
408047f369cytypedef isc_result_t
409047f369cy(*isc_timermgrcreatefunc_t)(isc_mem_t *mctx, isc_timermgr_t **managerp);
410047f369cy
411047f369cyisc_result_t
412047f369cyisc__timer_register(void);
413047f369cy/*%<
414047f369cy * Register a new timer management implementation and add it to the list of
415047f369cy * supported implementations.  This function must be called when a different
416047f369cy * event library is used than the one contained in the ISC library.
417047f369cy */
418047f369cy
419047f369cyisc_result_t
420047f369cyisc_timer_register(isc_timermgrcreatefunc_t createfunc);
421047f369cy/*%<
422047f369cy * A short cut function that specifies the timer management module in the ISC
423047f369cy * library for isc_timer_register().  An application that uses the ISC library
424047f369cy * usually do not have to care about this function: it would call
425047f369cy * isc_lib_register(), which internally calls this function.
426047f369cy */
427047f369cy#endif /* USE_TIMERIMPREGISTER */
428047f369cy
429d54cfbdrobertoISC_LANG_ENDDECLS
430d54cfbdroberto
431d54cfbdroberto#endif /* ISC_TIMER_H */
432