1258945Sroberto/*
2280849Scy * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
3258945Sroberto * Copyright (C) 1998-2002  Internet Software Consortium.
4258945Sroberto *
5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any
6258945Sroberto * purpose with or without fee is hereby granted, provided that the above
7258945Sroberto * copyright notice and this permission notice appear in all copies.
8258945Sroberto *
9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11258945Sroberto * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15258945Sroberto * PERFORMANCE OF THIS SOFTWARE.
16258945Sroberto */
17258945Sroberto
18280849Scy/* $Id: timer.h,v 1.43 2009/09/02 23:48:03 tbox Exp $ */
19258945Sroberto
20258945Sroberto#ifndef ISC_TIMER_H
21258945Sroberto#define ISC_TIMER_H 1
22258945Sroberto
23258945Sroberto/*****
24258945Sroberto ***** Module Info
25258945Sroberto *****/
26258945Sroberto
27258945Sroberto/*! \file isc/timer.h
28258945Sroberto * \brief Provides timers which are event sources in the task system.
29258945Sroberto *
30258945Sroberto * Three types of timers are supported:
31258945Sroberto *
32258945Sroberto *\li	'ticker' timers generate a periodic tick event.
33258945Sroberto *
34258945Sroberto *\li	'once' timers generate an idle timeout event if they are idle for too
35258945Sroberto *	long, and generate a life timeout event if their lifetime expires.
36258945Sroberto *	They are used to implement both (possibly expiring) idle timers and
37258945Sroberto *	'one-shot' timers.
38258945Sroberto *
39258945Sroberto *\li	'limited' timers generate a periodic tick event until they reach
40258945Sroberto *	their lifetime when they generate a life timeout event.
41258945Sroberto *
42258945Sroberto *\li	'inactive' timers generate no events.
43258945Sroberto *
44258945Sroberto * Timers can change type.  It is typical to create a timer as
45258945Sroberto * an 'inactive' timer and then change it into a 'ticker' or
46258945Sroberto * 'once' timer.
47258945Sroberto *
48258945Sroberto *\li MP:
49258945Sroberto *	The module ensures appropriate synchronization of data structures it
50258945Sroberto *	creates and manipulates.
51258945Sroberto *	Clients of this module must not be holding a timer's task's lock when
52258945Sroberto *	making a call that affects that timer.  Failure to follow this rule
53258945Sroberto *	can result in deadlock.
54258945Sroberto *	The caller must ensure that isc_timermgr_destroy() is called only
55258945Sroberto *	once for a given manager.
56258945Sroberto *
57258945Sroberto * \li Reliability:
58258945Sroberto *	No anticipated impact.
59258945Sroberto *
60258945Sroberto * \li Resources:
61258945Sroberto *	TBS
62258945Sroberto *
63258945Sroberto * \li Security:
64258945Sroberto *	No anticipated impact.
65258945Sroberto *
66258945Sroberto * \li Standards:
67258945Sroberto *	None.
68258945Sroberto */
69258945Sroberto
70258945Sroberto
71258945Sroberto/***
72258945Sroberto *** Imports
73258945Sroberto ***/
74258945Sroberto
75258945Sroberto#include <isc/types.h>
76258945Sroberto#include <isc/event.h>
77258945Sroberto#include <isc/eventclass.h>
78258945Sroberto#include <isc/lang.h>
79258945Sroberto#include <isc/time.h>
80258945Sroberto
81258945SrobertoISC_LANG_BEGINDECLS
82258945Sroberto
83258945Sroberto/***
84258945Sroberto *** Types
85258945Sroberto ***/
86258945Sroberto
87258945Sroberto/*% Timer Type */
88258945Srobertotypedef enum {
89258945Sroberto	isc_timertype_ticker = 0, 	/*%< Ticker */
90258945Sroberto	isc_timertype_once = 1, 	/*%< Once */
91258945Sroberto	isc_timertype_limited = 2, 	/*%< Limited */
92258945Sroberto	isc_timertype_inactive = 3 	/*%< Inactive */
93258945Sroberto} isc_timertype_t;
94258945Sroberto
95258945Srobertotypedef struct isc_timerevent {
96258945Sroberto	struct isc_event	common;
97258945Sroberto	isc_time_t		due;
98258945Sroberto} isc_timerevent_t;
99258945Sroberto
100258945Sroberto#define ISC_TIMEREVENT_FIRSTEVENT	(ISC_EVENTCLASS_TIMER + 0)
101258945Sroberto#define ISC_TIMEREVENT_TICK		(ISC_EVENTCLASS_TIMER + 1)
102258945Sroberto#define ISC_TIMEREVENT_IDLE		(ISC_EVENTCLASS_TIMER + 2)
103258945Sroberto#define ISC_TIMEREVENT_LIFE		(ISC_EVENTCLASS_TIMER + 3)
104258945Sroberto#define ISC_TIMEREVENT_LASTEVENT	(ISC_EVENTCLASS_TIMER + 65535)
105258945Sroberto
106280849Scy/*% Timer and timer manager methods */
107280849Scytypedef struct {
108280849Scy	void		(*destroy)(isc_timermgr_t **managerp);
109280849Scy	isc_result_t	(*timercreate)(isc_timermgr_t *manager,
110280849Scy				       isc_timertype_t type,
111280849Scy				       isc_time_t *expires,
112280849Scy				       isc_interval_t *interval,
113280849Scy				       isc_task_t *task,
114280849Scy				       isc_taskaction_t action,
115280849Scy				       const void *arg,
116280849Scy				       isc_timer_t **timerp);
117280849Scy} isc_timermgrmethods_t;
118280849Scy
119280849Scytypedef struct {
120280849Scy	void		(*attach)(isc_timer_t *timer, isc_timer_t **timerp);
121280849Scy	void		(*detach)(isc_timer_t **timerp);
122280849Scy	isc_result_t	(*reset)(isc_timer_t *timer, isc_timertype_t type,
123280849Scy				 isc_time_t *expires, isc_interval_t *interval,
124280849Scy				 isc_boolean_t purge);
125280849Scy	isc_result_t	(*touch)(isc_timer_t *timer);
126280849Scy} isc_timermethods_t;
127280849Scy
128280849Scy/*%
129280849Scy * This structure is actually just the common prefix of a timer manager
130280849Scy * object implementation's version of an isc_timermgr_t.
131280849Scy * \brief
132280849Scy * Direct use of this structure by clients is forbidden.  timer implementations
133280849Scy * may change the structure.  'magic' must be ISCAPI_TIMERMGR_MAGIC for any
134280849Scy * of the isc_timer_ routines to work.  timer implementations must maintain
135280849Scy * all timer invariants.
136280849Scy */
137280849Scystruct isc_timermgr {
138280849Scy	unsigned int		impmagic;
139280849Scy	unsigned int		magic;
140280849Scy	isc_timermgrmethods_t	*methods;
141280849Scy};
142280849Scy
143280849Scy#define ISCAPI_TIMERMGR_MAGIC		ISC_MAGIC('A','t','m','g')
144280849Scy#define ISCAPI_TIMERMGR_VALID(m)	((m) != NULL && \
145280849Scy					 (m)->magic == ISCAPI_TIMERMGR_MAGIC)
146280849Scy
147280849Scy/*%
148280849Scy * This is the common prefix of a timer object.  The same note as
149280849Scy * that for the timermgr structure applies.
150280849Scy */
151280849Scystruct isc_timer {
152280849Scy	unsigned int		impmagic;
153280849Scy	unsigned int		magic;
154280849Scy	isc_timermethods_t	*methods;
155280849Scy};
156280849Scy
157280849Scy#define ISCAPI_TIMER_MAGIC	ISC_MAGIC('A','t','m','r')
158280849Scy#define ISCAPI_TIMER_VALID(s)	((s) != NULL && \
159280849Scy				 (s)->magic == ISCAPI_TIMER_MAGIC)
160280849Scy
161258945Sroberto/***
162258945Sroberto *** Timer and Timer Manager Functions
163258945Sroberto ***
164258945Sroberto *** Note: all Ensures conditions apply only if the result is success for
165258945Sroberto *** those functions which return an isc_result_t.
166258945Sroberto ***/
167258945Sroberto
168258945Srobertoisc_result_t
169258945Srobertoisc_timer_create(isc_timermgr_t *manager,
170258945Sroberto		 isc_timertype_t type,
171258945Sroberto		 isc_time_t *expires,
172258945Sroberto		 isc_interval_t *interval,
173258945Sroberto		 isc_task_t *task,
174258945Sroberto		 isc_taskaction_t action,
175258945Sroberto		 const void *arg,
176258945Sroberto		 isc_timer_t **timerp);
177258945Sroberto/*%<
178258945Sroberto * Create a new 'type' timer managed by 'manager'.  The timers parameters
179258945Sroberto * are specified by 'expires' and 'interval'.  Events will be posted to
180258945Sroberto * 'task' and when dispatched 'action' will be called with 'arg' as the
181258945Sroberto * arg value.  The new timer is returned in 'timerp'.
182258945Sroberto *
183258945Sroberto * Notes:
184258945Sroberto *
185258945Sroberto *\li	For ticker timers, the timer will generate a 'tick' event every
186258945Sroberto *	'interval' seconds.  The value of 'expires' is ignored.
187258945Sroberto *
188258945Sroberto *\li	For once timers, 'expires' specifies the time when a life timeout
189258945Sroberto *	event should be generated.  If 'expires' is 0 (the epoch), then no life
190258945Sroberto *	timeout will be generated.  'interval' specifies how long the timer
191258945Sroberto *	can be idle before it generates an idle timeout.  If 0, then no
192258945Sroberto *	idle timeout will be generated.
193258945Sroberto *
194258945Sroberto *\li	If 'expires' is NULL, the epoch will be used.
195258945Sroberto *
196258945Sroberto *	If 'interval' is NULL, the zero interval will be used.
197258945Sroberto *
198258945Sroberto * Requires:
199258945Sroberto *
200258945Sroberto *\li	'manager' is a valid manager
201258945Sroberto *
202258945Sroberto *\li	'task' is a valid task
203258945Sroberto *
204258945Sroberto *\li	'action' is a valid action
205258945Sroberto *
206258945Sroberto *\li	'expires' points to a valid time, or is NULL.
207258945Sroberto *
208258945Sroberto *\li	'interval' points to a valid interval, or is NULL.
209258945Sroberto *
210258945Sroberto *\li	type == isc_timertype_inactive ||
211258945Sroberto *	('expires' and 'interval' are not both 0)
212258945Sroberto *
213258945Sroberto *\li	'timerp' is a valid pointer, and *timerp == NULL
214258945Sroberto *
215258945Sroberto * Ensures:
216258945Sroberto *
217258945Sroberto *\li	'*timerp' is attached to the newly created timer
218258945Sroberto *
219258945Sroberto *\li	The timer is attached to the task
220258945Sroberto *
221258945Sroberto *\li	An idle timeout will not be generated until at least Now + the
222258945Sroberto *	timer's interval if 'timer' is a once timer with a non-zero
223258945Sroberto *	interval.
224258945Sroberto *
225258945Sroberto * Returns:
226258945Sroberto *
227258945Sroberto *\li	Success
228258945Sroberto *\li	No memory
229258945Sroberto *\li	Unexpected error
230258945Sroberto */
231258945Sroberto
232258945Srobertoisc_result_t
233258945Srobertoisc_timer_reset(isc_timer_t *timer,
234258945Sroberto		isc_timertype_t type,
235258945Sroberto		isc_time_t *expires,
236258945Sroberto		isc_interval_t *interval,
237258945Sroberto		isc_boolean_t purge);
238258945Sroberto/*%<
239258945Sroberto * Change the timer's type, expires, and interval values to the given
240258945Sroberto * values.  If 'purge' is TRUE, any pending events from this timer
241258945Sroberto * are purged from its task's event queue.
242258945Sroberto *
243258945Sroberto * Notes:
244258945Sroberto *
245258945Sroberto *\li	If 'expires' is NULL, the epoch will be used.
246258945Sroberto *
247258945Sroberto *\li	If 'interval' is NULL, the zero interval will be used.
248258945Sroberto *
249258945Sroberto * Requires:
250258945Sroberto *
251258945Sroberto *\li	'timer' is a valid timer
252258945Sroberto *
253258945Sroberto *\li	The same requirements that isc_timer_create() imposes on 'type',
254258945Sroberto *	'expires' and 'interval' apply.
255258945Sroberto *
256258945Sroberto * Ensures:
257258945Sroberto *
258258945Sroberto *\li	An idle timeout will not be generated until at least Now + the
259258945Sroberto *	timer's interval if 'timer' is a once timer with a non-zero
260258945Sroberto *	interval.
261258945Sroberto *
262258945Sroberto * Returns:
263258945Sroberto *
264258945Sroberto *\li	Success
265258945Sroberto *\li	No memory
266258945Sroberto *\li	Unexpected error
267258945Sroberto */
268258945Sroberto
269258945Srobertoisc_result_t
270258945Srobertoisc_timer_touch(isc_timer_t *timer);
271258945Sroberto/*%<
272258945Sroberto * Set the last-touched time of 'timer' to the current time.
273258945Sroberto *
274258945Sroberto * Requires:
275258945Sroberto *
276258945Sroberto *\li	'timer' is a valid once timer.
277258945Sroberto *
278258945Sroberto * Ensures:
279258945Sroberto *
280258945Sroberto *\li	An idle timeout will not be generated until at least Now + the
281258945Sroberto *	timer's interval if 'timer' is a once timer with a non-zero
282258945Sroberto *	interval.
283258945Sroberto *
284258945Sroberto * Returns:
285258945Sroberto *
286258945Sroberto *\li	Success
287258945Sroberto *\li	Unexpected error
288258945Sroberto */
289258945Sroberto
290258945Srobertovoid
291258945Srobertoisc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp);
292258945Sroberto/*%<
293258945Sroberto * Attach *timerp to timer.
294258945Sroberto *
295258945Sroberto * Requires:
296258945Sroberto *
297258945Sroberto *\li	'timer' is a valid timer.
298258945Sroberto *
299258945Sroberto *\li	'timerp' points to a NULL timer.
300258945Sroberto *
301258945Sroberto * Ensures:
302258945Sroberto *
303258945Sroberto *\li	*timerp is attached to timer.
304258945Sroberto */
305258945Sroberto
306258945Srobertovoid
307258945Srobertoisc_timer_detach(isc_timer_t **timerp);
308258945Sroberto/*%<
309258945Sroberto * Detach *timerp from its timer.
310258945Sroberto *
311258945Sroberto * Requires:
312258945Sroberto *
313258945Sroberto *\li	'timerp' points to a valid timer.
314258945Sroberto *
315258945Sroberto * Ensures:
316258945Sroberto *
317258945Sroberto *\li	*timerp is NULL.
318258945Sroberto *
319258945Sroberto *\li	If '*timerp' is the last reference to the timer,
320258945Sroberto *	then:
321258945Sroberto *
322258945Sroberto *\code
323258945Sroberto *		The timer will be shutdown
324258945Sroberto *
325258945Sroberto *		The timer will detach from its task
326258945Sroberto *
327258945Sroberto *		All resources used by the timer have been freed
328258945Sroberto *
329258945Sroberto *		Any events already posted by the timer will be purged.
330258945Sroberto *		Therefore, if isc_timer_detach() is called in the context
331258945Sroberto *		of the timer's task, it is guaranteed that no more
332258945Sroberto *		timer event callbacks will run after the call.
333258945Sroberto *\endcode
334258945Sroberto */
335258945Sroberto
336258945Srobertoisc_timertype_t
337258945Srobertoisc_timer_gettype(isc_timer_t *timer);
338258945Sroberto/*%<
339258945Sroberto * Return the timer type.
340258945Sroberto *
341258945Sroberto * Requires:
342258945Sroberto *
343258945Sroberto *\li	'timer' to be a valid timer.
344258945Sroberto */
345258945Sroberto
346258945Srobertoisc_result_t
347280849Scyisc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
348280849Scy			 isc_timermgr_t **managerp);
349280849Scy
350280849Scyisc_result_t
351258945Srobertoisc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
352258945Sroberto/*%<
353280849Scy * Create a timer manager.  isc_timermgr_createinctx() also associates
354280849Scy * the new manager with the specified application context.
355258945Sroberto *
356258945Sroberto * Notes:
357258945Sroberto *
358258945Sroberto *\li	All memory will be allocated in memory context 'mctx'.
359258945Sroberto *
360258945Sroberto * Requires:
361258945Sroberto *
362258945Sroberto *\li	'mctx' is a valid memory context.
363258945Sroberto *
364258945Sroberto *\li	'managerp' points to a NULL isc_timermgr_t.
365258945Sroberto *
366280849Scy *\li	'actx' is a valid application context (for createinctx()).
367280849Scy *
368258945Sroberto * Ensures:
369258945Sroberto *
370258945Sroberto *\li	'*managerp' is a valid isc_timermgr_t.
371258945Sroberto *
372258945Sroberto * Returns:
373258945Sroberto *
374258945Sroberto *\li	Success
375258945Sroberto *\li	No memory
376258945Sroberto *\li	Unexpected error
377258945Sroberto */
378258945Sroberto
379258945Srobertovoid
380258945Srobertoisc_timermgr_destroy(isc_timermgr_t **managerp);
381258945Sroberto/*%<
382258945Sroberto * Destroy a timer manager.
383258945Sroberto *
384258945Sroberto * Notes:
385258945Sroberto *
386258945Sroberto *\li	This routine blocks until there are no timers left in the manager,
387258945Sroberto *	so if the caller holds any timer references using the manager, it
388258945Sroberto *	must detach them before calling isc_timermgr_destroy() or it will
389258945Sroberto *	block forever.
390258945Sroberto *
391258945Sroberto * Requires:
392258945Sroberto *
393258945Sroberto *\li	'*managerp' is a valid isc_timermgr_t.
394258945Sroberto *
395258945Sroberto * Ensures:
396258945Sroberto *
397258945Sroberto *\li	*managerp == NULL
398258945Sroberto *
399258945Sroberto *\li	All resources used by the manager have been freed.
400258945Sroberto */
401258945Sroberto
402258945Srobertovoid isc_timermgr_poke(isc_timermgr_t *m);
403258945Sroberto
404280849Scy#ifdef USE_TIMERIMPREGISTER
405280849Scy/*%<
406280849Scy * See isc_timermgr_create() above.
407280849Scy */
408280849Scytypedef isc_result_t
409280849Scy(*isc_timermgrcreatefunc_t)(isc_mem_t *mctx, isc_timermgr_t **managerp);
410280849Scy
411280849Scyisc_result_t
412280849Scyisc__timer_register(void);
413280849Scy/*%<
414280849Scy * Register a new timer management implementation and add it to the list of
415280849Scy * supported implementations.  This function must be called when a different
416280849Scy * event library is used than the one contained in the ISC library.
417280849Scy */
418280849Scy
419280849Scyisc_result_t
420280849Scyisc_timer_register(isc_timermgrcreatefunc_t createfunc);
421280849Scy/*%<
422280849Scy * A short cut function that specifies the timer management module in the ISC
423280849Scy * library for isc_timer_register().  An application that uses the ISC library
424280849Scy * usually do not have to care about this function: it would call
425280849Scy * isc_lib_register(), which internally calls this function.
426280849Scy */
427280849Scy#endif /* USE_TIMERIMPREGISTER */
428280849Scy
429258945SrobertoISC_LANG_ENDDECLS
430258945Sroberto
431258945Sroberto#endif /* ISC_TIMER_H */
432