3 * $Id: sel.h,v 1.9 2003/05/17 10:34:04 mdw Exp $
5 * I/O multiplexing support
7 * (c) 1999 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of the mLib utilities library.
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.
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.
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,
30 /*----- Revision history --------------------------------------------------*
33 * Revision 1.9 2003/05/17 10:34:04 mdw
34 * Tidying and bugfixing.
36 * Revision 1.8 2001/06/22 19:35:58 mdw
37 * Fix a large number of bugs.
39 * Revision 1.7 1999/12/10 23:42:04 mdw
40 * Change header file guard names.
42 * Revision 1.6 1999/08/31 17:42:22 mdw
43 * New function `sel_force' to force a descriptor to be `selected'.
45 * Revision 1.5 1999/08/19 18:30:26 mdw
46 * Implement hooks for foreign select-using systems (currently not well
49 * Revision 1.4 1999/05/22 13:39:15 mdw
50 * Change spelling of `multiplexor'. ;-)
52 * Revision 1.3 1999/05/17 20:36:36 mdw
53 * Make the selector type symbols an enumeration rather than a bunch of
56 * Revision 1.2 1999/05/15 10:33:32 mdw
57 * Fix copyright notices.
59 * Revision 1.1 1999/05/14 21:01:15 mdw
60 * Integrated `select' handling bits from the background resolver project.
71 /*----- Theory lesson -----------------------------------------------------*
73 * Things which are expecting to do I/O or go off at a certain time are
74 * called `selectors'. There are two types of selectors: `file selectors'
75 * wait patiently for a file to become readable or writable; `timeout
76 * selectors' wait for a certain amount of time to elapse. There is also a
77 * `multiplexor' which copes with managing all of this stuff.
79 * Multiplexors aren't actually very interesting. You initialize them with
80 * @sel_init@, and then add and remove selectors as you go. When you want to
81 * wait for something to happen, call @sel_select@.
83 * A file selector can *either* read *or* write. It can't do both. This is
84 * because you quite often want to read a socket but not write it; during
85 * those times you don't want to write, you just don't install a write
88 * File selectors are called when their files are available for reading or
89 * writing as appropriate, and given their file descriptor, the state of the
90 * file, and a pointer that was registered along with the selector.
92 * File selectors are set up in two phases. First, they're `initialized'
93 * with @sel_initfile@. An initialized file selector doesn't do anything.
94 * It needs to be added to a multiplexor using `sel_addfile'. It can later
95 * be removed using `sel_rmfile'. You can carry on adding and removing as
96 * you wish. Just don't try adding it twice in a row.
98 * Timeout selectors are called at a certain time. (Actually, they're called
99 * *after* a certain time.) There's no separate initialization step with
100 * timouts: you just add them and they work. If you decide you don't want a
101 * timeout to go off, then you just remove it. (Adding and removing the
102 * *same* timeout isn't something you do very often. You usually use a
103 * different expiry time each time.)
106 /*----- Header files ------------------------------------------------------*/
108 #include <sys/types.h>
109 #include <sys/time.h>
112 /*----- Data structures ---------------------------------------------------*/
114 /* --- A multiplexor --- *
116 * The files are sorted in reverse order of file descriptor number; the
117 * timers are in normal order of occurrence. Thus, the interesting one
118 * is always at the front of the list.
122 SEL_READ, /* File is ready to read */
123 SEL_WRITE, /* File is ready to write */
124 SEL_EXC, /* Something odd has happened */
125 SEL_MODES /* Number of modes available */
128 typedef struct sel_state {
129 struct sel_file *files[SEL_MODES]; /* Lists of interesting files */
130 struct sel_timer *timers; /* List of timers */
131 struct sel_hook *hooks; /* List of hook functions applied */
132 fd_set fd[SEL_MODES]; /* Quick reference table for files */
133 struct sel_args *args; /* Pointer to arguments */
136 /* --- Listening for a file --- */
138 typedef struct sel_file {
139 struct sel_file *next; /* Next file in the list */
140 struct sel_file **prev; /* Previous file in the list */
141 struct sel_state *s; /* Pointer to select multiplexor */
142 int fd; /* File descriptor */
143 unsigned mode; /* Interesting event for file */
144 void (*func)(int /*fd*/, unsigned /*mode*/, void */*p*/); /* Handler */
145 void *p; /* Argument for the handler */
146 struct sel_pendfile *pend; /* Pending file information */
149 /* --- Waiting for a timeout --- */
151 typedef struct sel_timer {
152 struct sel_timer *next; /* Next timer in the list */
153 struct sel_timer **prev; /* Previous timer in the list */
154 struct timeval tv; /* Real time when timer should go */
155 void (*func)(struct timeval */*tv*/, void */*p*/); /* Handler function */
156 void *p; /* Argument for the handler */
157 struct sel_pendtimer *pend; /* Pending timer information */
160 /* --- A select argument block --- */
162 typedef struct sel_args {
163 int maxfd; /* Highest-numbered file */
164 fd_set fd[SEL_MODES]; /* Bit flags for all the files */
165 struct timeval tv, *tvp; /* Time to return */
166 struct timeval now; /* Current time */
169 /* --- A selector hook --- *
171 * The hooks are called (in arbitrary order) on each select.
174 typedef void (*sel_hookfn)(sel_state */*s*/,
178 typedef struct sel_hook {
179 struct sel_hook *next; /* Next hook in the list */
180 struct sel_hook **prev; /* Previous hook in the list */
181 sel_hookfn before, after; /* Hook functions */
182 void *p; /* Argument for the hook functions */
185 /*----- Functions provided ------------------------------------------------*/
187 /* --- @sel_init@ --- *
189 * Arguments: @sel_state *s@ = pointer to a state block to initialize
193 * Use: Initializes a select state block.
196 extern void sel_init(sel_state */*s*/);
198 /* --- @sel_initfile@ --- *
200 * Arguments: @sel_state *s@ = select state to attach to
201 * @sel_file *f@ = pointer to a file block to initialize
202 * @int fd@ = the file descriptor to listen to
203 * @unsigned mode@ = what to listen for
204 * @void (*func)(int fd, unsigned mode, void *p)@ = handler
205 * @void *p@ = argument to pass to handler
209 * Use: Initializes a file block ready for use. The file block
210 * isn't added to the list of things to do until a call to
214 extern void sel_initfile(sel_state */*s*/, sel_file */*f*/,
215 int /*fd*/, unsigned /*mode*/,
216 void (*/*func*/)(int /*fd*/,
221 /* --- @sel_addfile@ --- *
223 * Arguments: @sel_file *f@ = pointer to a file block
227 * Use: Adds a file block into the list of things to listen to.
230 extern void sel_addfile(sel_file */*f*/);
232 /* --- @sel_rmfile@ --- *
234 * Arguments: @sel_file *f@ = pointer to a file block
238 * Use: Removes a file block from the list of things to listen to.
241 extern void sel_rmfile(sel_file */*f*/);
243 /* --- @sel_force@ --- *
245 * Arguments: @sel_file *f@ = pointer to file selector
249 * Use: Forces a file selector to be considered ready. This is only
250 * useful during a call to @sel_select@. Of particular use is
251 * forcing a write selector when there's something interesting
255 extern void sel_force(sel_file */*f*/);
257 /* --- @sel_addtimer@ --- *
259 * Arguments: @sel_state *s@ = pointer to a state block
260 * @sel_timer *t@ = pointer to a timer block
261 * @struct timeval *tv@ = pointer to time to activate
262 * @void *p@ = argument for handler function
266 * Use: Registers and sets up a timer.
269 extern void sel_addtimer(sel_state */*s*/, sel_timer */*t*/,
270 struct timeval */*tv*/,
271 void (*/*func*/)(struct timeval */*tv*/,
275 /* --- @sel_rmtimer@ --- *
277 * Arguments: @sel_timer *t@ = pointer to timer block
281 * Use: Removes a timer from the list of timers.
284 extern void sel_rmtimer(sel_timer */*t*/);
286 /* --- @sel_addhook@ --- *
288 * Arguments: @sel_state *s@ = pointer to state block
289 * @sel_hook *h@ = pointer to hook block
290 * @sel_hookfn before, after@ = hook functions
291 * @void *p@ = pointer argument to pass to hook functions
295 * Use: Registers hook functions to be called on each select call.
298 extern void sel_addhook(sel_state */*s*/, sel_hook */*h*/,
299 sel_hookfn /*before*/, sel_hookfn /*after*/,
302 /* --- @sel_rmhook@ --- *
304 * Arguments: @sel_hook *h@ = pointer to hook block
308 * Use: Removes hook functions.
311 extern void sel_rmhook(sel_hook */*h*/);
313 /* --- @sel_fdmerge@ --- *
315 * Arguments: @fd_set *dest@ = destination FD set
316 * @fd_set *fd@ = pointer to set to merge
317 * @int maxfd@ = highest numbered descriptor in @fd@ + 1
319 * Returns: Actual highest numbered descriptor.
321 * Use: Merges file descriptor sets, and returns an accurate @maxfd@
325 extern int sel_fdmerge(fd_set */*dest*/, fd_set */*fd*/, int /*maxfd*/);
327 /* --- @sel_select@ --- *
329 * Arguments: @sel_state *s@ = pointer to state block
331 * Returns: Zero if all OK, -1 on error.
333 * Use: Does a @select@ call (or equivalent @poll@).
336 extern int sel_select(sel_state */*s*/);
338 /*----- That's all, folks -------------------------------------------------*/