1/*
2 * Copyright (C) 2004-2008  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.40 2008/06/23 23:47:11 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/***
107 *** Timer and Timer Manager Functions
108 ***
109 *** Note: all Ensures conditions apply only if the result is success for
110 *** those functions which return an isc_result_t.
111 ***/
112
113isc_result_t
114isc_timer_create(isc_timermgr_t *manager,
115		 isc_timertype_t type,
116		 isc_time_t *expires,
117		 isc_interval_t *interval,
118		 isc_task_t *task,
119		 isc_taskaction_t action,
120		 const void *arg,
121		 isc_timer_t **timerp);
122/*%<
123 * Create a new 'type' timer managed by 'manager'.  The timers parameters
124 * are specified by 'expires' and 'interval'.  Events will be posted to
125 * 'task' and when dispatched 'action' will be called with 'arg' as the
126 * arg value.  The new timer is returned in 'timerp'.
127 *
128 * Notes:
129 *
130 *\li	For ticker timers, the timer will generate a 'tick' event every
131 *	'interval' seconds.  The value of 'expires' is ignored.
132 *
133 *\li	For once timers, 'expires' specifies the time when a life timeout
134 *	event should be generated.  If 'expires' is 0 (the epoch), then no life
135 *	timeout will be generated.  'interval' specifies how long the timer
136 *	can be idle before it generates an idle timeout.  If 0, then no
137 *	idle timeout will be generated.
138 *
139 *\li	If 'expires' is NULL, the epoch will be used.
140 *
141 *	If 'interval' is NULL, the zero interval will be used.
142 *
143 * Requires:
144 *
145 *\li	'manager' is a valid manager
146 *
147 *\li	'task' is a valid task
148 *
149 *\li	'action' is a valid action
150 *
151 *\li	'expires' points to a valid time, or is NULL.
152 *
153 *\li	'interval' points to a valid interval, or is NULL.
154 *
155 *\li	type == isc_timertype_inactive ||
156 *	('expires' and 'interval' are not both 0)
157 *
158 *\li	'timerp' is a valid pointer, and *timerp == NULL
159 *
160 * Ensures:
161 *
162 *\li	'*timerp' is attached to the newly created timer
163 *
164 *\li	The timer is attached to the task
165 *
166 *\li	An idle timeout will not be generated until at least Now + the
167 *	timer's interval if 'timer' is a once timer with a non-zero
168 *	interval.
169 *
170 * Returns:
171 *
172 *\li	Success
173 *\li	No memory
174 *\li	Unexpected error
175 */
176
177isc_result_t
178isc_timer_reset(isc_timer_t *timer,
179		isc_timertype_t type,
180		isc_time_t *expires,
181		isc_interval_t *interval,
182		isc_boolean_t purge);
183/*%<
184 * Change the timer's type, expires, and interval values to the given
185 * values.  If 'purge' is TRUE, any pending events from this timer
186 * are purged from its task's event queue.
187 *
188 * Notes:
189 *
190 *\li	If 'expires' is NULL, the epoch will be used.
191 *
192 *\li	If 'interval' is NULL, the zero interval will be used.
193 *
194 * Requires:
195 *
196 *\li	'timer' is a valid timer
197 *
198 *\li	The same requirements that isc_timer_create() imposes on 'type',
199 *	'expires' and 'interval' apply.
200 *
201 * Ensures:
202 *
203 *\li	An idle timeout will not be generated until at least Now + the
204 *	timer's interval if 'timer' is a once timer with a non-zero
205 *	interval.
206 *
207 * Returns:
208 *
209 *\li	Success
210 *\li	No memory
211 *\li	Unexpected error
212 */
213
214isc_result_t
215isc_timer_touch(isc_timer_t *timer);
216/*%<
217 * Set the last-touched time of 'timer' to the current time.
218 *
219 * Requires:
220 *
221 *\li	'timer' is a valid once timer.
222 *
223 * Ensures:
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	Unexpected error
233 */
234
235void
236isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp);
237/*%<
238 * Attach *timerp to timer.
239 *
240 * Requires:
241 *
242 *\li	'timer' is a valid timer.
243 *
244 *\li	'timerp' points to a NULL timer.
245 *
246 * Ensures:
247 *
248 *\li	*timerp is attached to timer.
249 */
250
251void
252isc_timer_detach(isc_timer_t **timerp);
253/*%<
254 * Detach *timerp from its timer.
255 *
256 * Requires:
257 *
258 *\li	'timerp' points to a valid timer.
259 *
260 * Ensures:
261 *
262 *\li	*timerp is NULL.
263 *
264 *\li	If '*timerp' is the last reference to the timer,
265 *	then:
266 *
267 *\code
268 *		The timer will be shutdown
269 *
270 *		The timer will detach from its task
271 *
272 *		All resources used by the timer have been freed
273 *
274 *		Any events already posted by the timer will be purged.
275 *		Therefore, if isc_timer_detach() is called in the context
276 *		of the timer's task, it is guaranteed that no more
277 *		timer event callbacks will run after the call.
278 *\endcode
279 */
280
281isc_timertype_t
282isc_timer_gettype(isc_timer_t *timer);
283/*%<
284 * Return the timer type.
285 *
286 * Requires:
287 *
288 *\li	'timer' to be a valid timer.
289 */
290
291isc_result_t
292isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
293/*%<
294 * Create a timer manager.
295 *
296 * Notes:
297 *
298 *\li	All memory will be allocated in memory context 'mctx'.
299 *
300 * Requires:
301 *
302 *\li	'mctx' is a valid memory context.
303 *
304 *\li	'managerp' points to a NULL isc_timermgr_t.
305 *
306 * Ensures:
307 *
308 *\li	'*managerp' is a valid isc_timermgr_t.
309 *
310 * Returns:
311 *
312 *\li	Success
313 *\li	No memory
314 *\li	Unexpected error
315 */
316
317void
318isc_timermgr_destroy(isc_timermgr_t **managerp);
319/*%<
320 * Destroy a timer manager.
321 *
322 * Notes:
323 *
324 *\li	This routine blocks until there are no timers left in the manager,
325 *	so if the caller holds any timer references using the manager, it
326 *	must detach them before calling isc_timermgr_destroy() or it will
327 *	block forever.
328 *
329 * Requires:
330 *
331 *\li	'*managerp' is a valid isc_timermgr_t.
332 *
333 * Ensures:
334 *
335 *\li	*managerp == NULL
336 *
337 *\li	All resources used by the manager have been freed.
338 */
339
340void isc_timermgr_poke(isc_timermgr_t *m);
341
342ISC_LANG_ENDDECLS
343
344#endif /* ISC_TIMER_H */
345