chiark / gitweb /
Various fixes.
[mLib] / sel.h
CommitLineData
97f65b00 1/* -*-c-*-
2 *
0a2a19b4 3 * $Id: sel.h,v 1.8 2001/06/22 19:35:58 mdw Exp $
97f65b00 4 *
5 * I/O multiplexing support
6 *
a3ddb778 7 * (c) 1999 Straylight/Edgeware
97f65b00 8 */
9
10/*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of the mLib utilities library.
13 *
14 * mLib is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * mLib is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU Library General Public
25 * License along with mLib; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 * MA 02111-1307, USA.
28 */
29
30/*----- Revision history --------------------------------------------------*
31 *
32 * $Log: sel.h,v $
0a2a19b4 33 * Revision 1.8 2001/06/22 19:35:58 mdw
34 * Fix a large number of bugs.
35 *
c6e0eaf0 36 * Revision 1.7 1999/12/10 23:42:04 mdw
37 * Change header file guard names.
38 *
1101f87a 39 * Revision 1.6 1999/08/31 17:42:22 mdw
40 * New function `sel_force' to force a descriptor to be `selected'.
41 *
1226c514 42 * Revision 1.5 1999/08/19 18:30:26 mdw
43 * Implement hooks for foreign select-using systems (currently not well
44 * tested).
45 *
d6232a7a 46 * Revision 1.4 1999/05/22 13:39:15 mdw
47 * Change spelling of `multiplexor'. ;-)
48 *
e32dabae 49 * Revision 1.3 1999/05/17 20:36:36 mdw
50 * Make the selector type symbols an enumeration rather than a bunch of
51 * #defines.
52 *
a3ddb778 53 * Revision 1.2 1999/05/15 10:33:32 mdw
54 * Fix copyright notices.
55 *
97f65b00 56 * Revision 1.1 1999/05/14 21:01:15 mdw
57 * Integrated `select' handling bits from the background resolver project.
58 *
59 */
60
c6e0eaf0 61#ifndef MLIB_SEL_H
62#define MLIB_SEL_H
97f65b00 63
64#ifdef __cplusplus
65 extern "C" {
66#endif
67
68/*----- Theory lesson -----------------------------------------------------*
69 *
70 * Things which are expecting to do I/O or go off at a certain time are
71 * called `selectors'. There are two types of selectors: `file selectors'
72 * wait patiently for a file to become readable or writable; `timeout
73 * selectors' wait for a certain amount of time to elapse. There is also a
74 * `multiplexor' which copes with managing all of this stuff.
75 *
76 * Multiplexors aren't actually very interesting. You initialize them with
77 * @sel_init@, and then add and remove selectors as you go. When you want to
78 * wait for something to happen, call @sel_select@.
79 *
80 * A file selector can *either* read *or* write. It can't do both. This is
81 * because you quite often want to read a socket but not write it; during
82 * those times you don't want to write, you just don't install a write
83 * selector.
84 *
85 * File selectors are called when their files are available for reading or
86 * writing as appropriate, and given their file descriptor, the state of the
87 * file, and a pointer that was registered along with the selector.
88 *
89 * File selectors are set up in two phases. First, they're `initialized'
90 * with @sel_initfile@. An initialized file selector doesn't do anything.
91 * It needs to be added to a multiplexor using `sel_addfile'. It can later
92 * be removed using `sel_rmfile'. You can carry on adding and removing as
93 * you wish. Just don't try adding it twice in a row.
94 *
95 * Timeout selectors are called at a certain time. (Actually, they're called
96 * *after* a certain time.) There's no separate initialization step with
97 * timouts: you just add them and they work. If you decide you don't want a
98 * timeout to go off, then you just remove it. (Adding and removing the
99 * *same* timeout isn't something you do very often. You usually use a
100 * different expiry time each time.)
101 */
102
103/*----- Header files ------------------------------------------------------*/
104
105#include <sys/types.h>
106#include <sys/time.h>
107#include <unistd.h>
108
109/*----- Data structures ---------------------------------------------------*/
110
1226c514 111/* --- A multiplexor --- *
112 *
113 * The files are sorted in reverse order of file descriptor number; the
114 * timers are in normal order of occurrence. Thus, the interesting one
115 * is always at the front of the list.
116 */
117
118enum {
1101f87a 119 SEL_READ, /* File is ready to read */
120 SEL_WRITE, /* File is ready to write */
121 SEL_EXC, /* Something odd has happened */
122 SEL_MODES /* Number of modes available */
1226c514 123};
124
125typedef struct sel_state {
1101f87a 126 struct sel_file *files[SEL_MODES]; /* Lists of interesting files */
127 struct sel_timer *timers; /* List of timers */
128 struct sel_hook *hooks; /* List of hook functions applied */
129 fd_set fd[SEL_MODES]; /* Quick reference table for files */
130 struct sel_args *args; /* Pointer to arguments */
1226c514 131} sel_state;
132
97f65b00 133/* --- Listening for a file --- */
134
135typedef struct sel_file {
1101f87a 136 struct sel_file *next; /* Next file in the list */
137 struct sel_file *prev; /* Previous file in the list */
138 struct sel_state *s; /* Pointer to select multiplexor */
139 int fd; /* File descriptor */
140 unsigned mode; /* Interesting event for file */
141 void (*func)(int /*fd*/, unsigned /*mode*/, void */*p*/); /* Handler */
142 void *p; /* Argument for the handler */
0a2a19b4 143 struct sel_pendfile *pend; /* Pending file information */
97f65b00 144} sel_file;
145
97f65b00 146/* --- Waiting for a timeout --- */
147
148typedef struct sel_timer {
1101f87a 149 struct sel_timer *next; /* Next timer in the list */
150 struct sel_timer *prev; /* Previous timer in the list */
151 struct timeval tv; /* Real time when timer should go */
152 void (*func)(struct timeval */*tv*/, void */*p*/); /* Handler function */
153 void *p; /* Argument for the handler */
0a2a19b4 154 struct sel_pendtimer *pend; /* Pending timer information */
97f65b00 155} sel_timer;
156
1226c514 157/* --- A select argument block --- */
158
159typedef struct sel_args {
1101f87a 160 int maxfd; /* Highest-numbered file */
161 fd_set fd[SEL_MODES]; /* Bit flags for all the files */
162 struct timeval tv, *tvp; /* Time to return */
163 struct timeval now; /* Current time */
1226c514 164} sel_args;
165
166/* --- A selector hook --- *
97f65b00 167 *
1226c514 168 * The hooks are called (in arbitrary order) on each select.
97f65b00 169 */
170
1226c514 171typedef void (*sel_hookfn)(sel_state */*s*/,
172 sel_args */*a*/,
173 void */*p*/);
174
175typedef struct sel_hook {
1101f87a 176 struct sel_hook *next; /* Next hook in the list */
177 struct sel_hook *prev; /* Previous hook in the list */
178 sel_hookfn before, after; /* Hook functions */
179 void *p; /* Argument for the hook functions */
1226c514 180} sel_hook;
97f65b00 181
182/*----- Functions provided ------------------------------------------------*/
183
184/* --- @sel_init@ --- *
185 *
186 * Arguments: @sel_state *s@ = pointer to a state block to initialize
187 *
188 * Returns: ---
189 *
190 * Use: Initializes a select state block.
191 */
192
193extern void sel_init(sel_state */*s*/);
194
195/* --- @sel_initfile@ --- *
196 *
197 * Arguments: @sel_state *s@ = select state to attach to
198 * @sel_file *f@ = pointer to a file block to initialize
199 * @int fd@ = the file descriptor to listen to
200 * @unsigned mode@ = what to listen for
201 * @void (*func)(int fd, unsigned mode, void *p)@ = handler
202 * @void *p@ = argument to pass to handler
203 *
204 * Returns: ---
205 *
206 * Use: Initializes a file block ready for use. The file block
207 * isn't added to the list of things to do until a call to
208 * @sel_addfile@.
209 */
210
211extern void sel_initfile(sel_state */*s*/, sel_file */*f*/,
212 int /*fd*/, unsigned /*mode*/,
213 void (*/*func*/)(int /*fd*/,
214 unsigned /*mode*/,
215 void */*p*/),
216 void */*p*/);
217
218/* --- @sel_addfile@ --- *
219 *
220 * Arguments: @sel_file *f@ = pointer to a file block
221 *
222 * Returns: ---
223 *
224 * Use: Adds a file block into the list of things to listen to.
225 */
226
227extern void sel_addfile(sel_file */*f*/);
228
229/* --- @sel_rmfile@ --- *
230 *
231 * Arguments: @sel_file *f@ = pointer to a file block
232 *
233 * Returns: ---
234 *
235 * Use: Removes a file block from the list of things to listen to.
236 */
237
238extern void sel_rmfile(sel_file */*f*/);
239
1101f87a 240/* --- @sel_force@ --- *
241 *
242 * Arguments: @sel_file *f@ = pointer to file selector
243 *
244 * Returns: ---
245 *
246 * Use: Forces a file selector to be considered ready. This is only
247 * useful during a call to @sel_select@. Of particular use is
248 * forcing a write selector when there's something interesting
249 * ready for it.
250 */
251
252extern void sel_force(sel_file */*f*/);
253
97f65b00 254/* --- @sel_addtimer@ --- *
255 *
256 * Arguments: @sel_state *s@ = pointer to a state block
257 * @sel_timer *t@ = pointer to a timer block
258 * @struct timeval *tv@ = pointer to time to activate
97f65b00 259 * @void *p@ = argument for handler function
260 *
261 * Returns: ---
262 *
263 * Use: Registers and sets up a timer.
264 */
265
266extern void sel_addtimer(sel_state */*s*/, sel_timer */*t*/,
267 struct timeval */*tv*/,
268 void (*/*func*/)(struct timeval */*tv*/,
269 void */*p*/),
270 void */*p*/);
271
272/* --- @sel_rmtimer@ --- *
273 *
274 * Arguments: @sel_timer *t@ = pointer to timer block
275 *
276 * Returns: ---
277 *
278 * Use: Removes a timer from the list of timers.
279 */
280
281extern void sel_rmtimer(sel_timer */*t*/);
282
1226c514 283/* --- @sel_addhook@ --- *
284 *
285 * Arguments: @sel_state *s@ = pointer to state block
286 * @sel_hook *h@ = pointer to hook block
287 * @sel_hookfn before, after@ = hook functions
288 * @void *p@ = pointer argument to pass to hook functions
289 *
290 * Returns: ---
291 *
292 * Use: Registers hook functions to be called on each select call.
293 */
294
295extern void sel_addhook(sel_state */*s*/, sel_hook */*h*/,
296 sel_hookfn /*before*/, sel_hookfn /*after*/,
297 void */*p*/);
298
299/* --- @sel_rmhook@ --- *
300 *
301 * Arguments: @sel_hook *h@ = pointer to hook block
302 *
303 * Returns: ---
304 *
305 * Use: Removes hook functions.
306 */
307
308extern void sel_rmhook(sel_hook */*h*/);
309
310/* --- @sel_fdmerge@ --- *
311 *
312 * Arguments: @fd_set *dest@ = destination FD set
313 * @fd_set *fd@ = pointer to set to merge
314 * @int maxfd@ = highest numbered descriptor in @fd@ + 1
315 *
316 * Returns: Actual highest numbered descriptor.
317 *
318 * Use: Merges file descriptor sets, and returns an accurate @maxfd@
319 * value.
320 */
321
322extern int sel_fdmerge(fd_set */*dest*/, fd_set */*fd*/, int /*maxfd*/);
323
97f65b00 324/* --- @sel_select@ --- *
325 *
326 * Arguments: @sel_state *s@ = pointer to state block
327 *
328 * Returns: Zero if all OK, -1 on error.
329 *
330 * Use: Does a @select@ call (or equivalent @poll@).
331 */
332
333extern int sel_select(sel_state */*s*/);
334
335/*----- That's all, folks -------------------------------------------------*/
336
337#ifdef __cplusplus
338 }
339#endif
340
341#endif