xref: /openbsd/usr.bin/dig/lib/isc/include/isc/timer.h (revision 1fb015a8)
1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14  * PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /* $Id: timer.h,v 1.13 2020/09/14 08:40:44 florian Exp $ */
18 
19 #ifndef ISC_TIMER_H
20 #define ISC_TIMER_H 1
21 
22 /*****
23  ***** Module Info
24  *****/
25 
26 /*! \file isc/timer.h
27  * \brief Provides timers which are event sources in the task system.
28  *
29  * Three types of timers are supported:
30  *
31  *\li	'ticker' timers generate a periodic tick event.
32  *
33  *\li	'once' timers generate an idle timeout event if they are idle for too
34  *	long, and generate a life timeout event if their lifetime expires.
35  *	They are used to implement both (possibly expiring) idle timers and
36  *	'one-shot' timers.
37  *
38  *\li	'limited' timers generate a periodic tick event until they reach
39  *	their lifetime when they generate a life timeout event.
40  *
41  *\li	'inactive' timers generate no events.
42  *
43  * Timers can change type.  It is typical to create a timer as
44  * an 'inactive' timer and then change it into a 'ticker' or
45  * 'once' timer.
46  *
47  *\li MP:
48  *	The module ensures appropriate synchronization of data structures it
49  *	creates and manipulates.
50  *	Clients of this module must not be holding a timer's task's lock when
51  *	making a call that affects that timer.  Failure to follow this rule
52  *	can result in deadlock.
53  *	The caller must ensure that isc_timermgr_destroy() is called only
54  *	once for a given manager.
55  *
56  * \li Reliability:
57  *	No anticipated impact.
58  *
59  * \li Resources:
60  *	TBS
61  *
62  * \li Security:
63  *	No anticipated impact.
64  *
65  * \li Standards:
66  *	None.
67  */
68 
69 /***
70  *** Imports
71  ***/
72 
73 #include <time.h>
74 
75 #include <isc/types.h>
76 #include <isc/event.h>
77 #include <isc/eventclass.h>
78 
79 /***
80  *** Types
81  ***/
82 
83 /*% Timer Type */
84 
85 typedef struct isc_timerevent {
86 	struct isc_event	common;
87 	struct timespec		due;
88 } isc_timerevent_t;
89 
90 #define ISC_TIMEREVENT_FIRSTEVENT	(ISC_EVENTCLASS_TIMER + 0)
91 #define ISC_TIMEREVENT_TICK		(ISC_EVENTCLASS_TIMER + 1)
92 #define ISC_TIMEREVENT_IDLE		(ISC_EVENTCLASS_TIMER + 2)
93 #define ISC_TIMEREVENT_LIFE		(ISC_EVENTCLASS_TIMER + 3)
94 #define ISC_TIMEREVENT_LASTEVENT	(ISC_EVENTCLASS_TIMER + 65535)
95 
96 /***
97  *** Timer and Timer Manager Functions
98  ***
99  *** Note: all Ensures conditions apply only if the result is success for
100  *** those functions which return an isc_result_t.
101  ***/
102 
103 isc_result_t
104 isc_timer_create(isc_timermgr_t *manager,
105 		 const struct timespec *interval,
106 		 isc_task_t *task,
107 		 isc_taskaction_t action,
108 		 void *arg,
109 		 isc_timer_t **timerp);
110 /*%<
111  * Create a new 'type' timer managed by 'manager'.  The timers parameters
112  * are specified by 'expires' and 'interval'.  Events will be posted to
113  * 'task' and when dispatched 'action' will be called with 'arg' as the
114  * arg value.  The new timer is returned in 'timerp'.
115  *
116  * Notes:
117  *
118  *\li	For ticker timers, the timer will generate a 'tick' event every
119  *	'interval' seconds.  The value of 'expires' is ignored.
120  *
121  *\li	For once timers, 'expires' specifies the time when a life timeout
122  *	event should be generated.  If 'expires' is 0 (the epoch), then no life
123  *	timeout will be generated.  'interval' specifies how long the timer
124  *	can be idle before it generates an idle timeout.  If 0, then no
125  *	idle timeout will be generated.
126  *
127  *\li	If 'expires' is NULL, the epoch will be used.
128  *
129  *	If 'interval' is NULL, the zero interval will be used.
130  *
131  * Requires:
132  *
133  *\li	'manager' is a valid manager
134  *
135  *\li	'task' is a valid task
136  *
137  *\li	'action' is a valid action
138  *
139  *\li	'expires' points to a valid time, or is NULL.
140  *
141  *\li	'interval' points to a valid interval, or is NULL.
142  *
143  *\li	type == isc_timertype_inactive ||
144  *	('expires' and 'interval' are not both 0)
145  *
146  *\li	'timerp' is a valid pointer, and *timerp == NULL
147  *
148  * Ensures:
149  *
150  *\li	'*timerp' is attached to the newly created timer
151  *
152  *\li	The timer is attached to the task
153  *
154  *\li	An idle timeout will not be generated until at least Now + the
155  *	timer's interval if 'timer' is a once timer with a non-zero
156  *	interval.
157  *
158  * Returns:
159  *
160  *\li	Success
161  *\li	No memory
162  *\li	Unexpected error
163  */
164 
165 isc_result_t
166 isc_timer_reset(isc_timer_t *timer,
167 		const struct timespec *interval,
168 		int purge);
169 /*%<
170  * Change the timer's type, expires, and interval values to the given
171  * values.  If 'purge' is TRUE, any pending events from this timer
172  * are purged from its task's event queue.
173  *
174  * Notes:
175  *
176  *\li	If 'expires' is NULL, the epoch will be used.
177  *
178  *\li	If 'interval' is NULL, the zero interval will be used.
179  *
180  * Requires:
181  *
182  *\li	'timer' is a valid timer
183  *
184  *\li	The same requirements that isc_timer_create() imposes on 'type',
185  *	'expires' and 'interval' apply.
186  *
187  * Ensures:
188  *
189  *\li	An idle timeout will not be generated until at least Now + the
190  *	timer's interval if 'timer' is a once timer with a non-zero
191  *	interval.
192  *
193  * Returns:
194  *
195  *\li	Success
196  *\li	No memory
197  *\li	Unexpected error
198  */
199 
200 void
201 isc_timer_touch(isc_timer_t *timer);
202 /*%<
203  * Set the last-touched time of 'timer' to the current time.
204  *
205  * Requires:
206  *
207  *\li	'timer' is a valid once timer.
208  *
209  * Ensures:
210  *
211  *\li	An idle timeout will not be generated until at least Now + the
212  *	timer's interval if 'timer' is a once timer with a non-zero
213  *	interval.
214  *
215  */
216 
217 void
218 isc_timer_detach(isc_timer_t **timerp);
219 /*%<
220  * Detach *timerp from its timer.
221  *
222  * Requires:
223  *
224  *\li	'timerp' points to a valid timer.
225  *
226  * Ensures:
227  *
228  *\li	*timerp is NULL.
229  *
230  *\li	If '*timerp' is the last reference to the timer,
231  *	then:
232  *
233  *\code
234  *		The timer will be shutdown
235  *
236  *		The timer will detach from its task
237  *
238  *		All resources used by the timer have been freed
239  *
240  *		Any events already posted by the timer will be purged.
241  *		Therefore, if isc_timer_detach() is called in the context
242  *		of the timer's task, it is guaranteed that no more
243  *		timer event callbacks will run after the call.
244  *\endcode
245  */
246 
247 isc_result_t
248 isc_timermgr_create(isc_timermgr_t **managerp);
249 /*%<
250  * Create a timer manager.  isc_timermgr_createinctx() also associates
251  * the new manager with the specified application context.
252  *
253  * Notes:
254  *
255  *\li	All memory will be allocated in memory context 'mctx'.
256  *
257  * Requires:
258  *
259  *\li	'mctx' is a valid memory context.
260  *
261  *\li	'managerp' points to a NULL isc_timermgr_t.
262  *
263  *\li	'actx' is a valid application context (for createinctx()).
264  *
265  * Ensures:
266  *
267  *\li	'*managerp' is a valid isc_timermgr_t.
268  *
269  * Returns:
270  *
271  *\li	Success
272  *\li	No memory
273  *\li	Unexpected error
274  */
275 
276 void
277 isc_timermgr_destroy(isc_timermgr_t **managerp);
278 /*%<
279  * Destroy a timer manager.
280  *
281  * Notes:
282  *
283  *\li	This routine blocks until there are no timers left in the manager,
284  *	so if the caller holds any timer references using the manager, it
285  *	must detach them before calling isc_timermgr_destroy() or it will
286  *	block forever.
287  *
288  * Requires:
289  *
290  *\li	'*managerp' is a valid isc_timermgr_t.
291  *
292  * Ensures:
293  *
294  *\li	*managerp == NULL
295  *
296  *\li	All resources used by the manager have been freed.
297  */
298 
299 #endif /* ISC_TIMER_H */
300