chiark / gitweb /
Track @dstr_vputf@ interface change.
[mLib] / sel.h
1 /* -*-c-*-
2  *
3  * $Id: sel.h,v 1.8 2001/06/22 19:35:58 mdw Exp $
4  *
5  * I/O multiplexing support
6  *
7  * (c) 1999 Straylight/Edgeware
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 $
33  * Revision 1.8  2001/06/22 19:35:58  mdw
34  * Fix a large number of bugs.
35  *
36  * Revision 1.7  1999/12/10 23:42:04  mdw
37  * Change header file guard names.
38  *
39  * Revision 1.6  1999/08/31 17:42:22  mdw
40  * New function `sel_force' to force a descriptor to be `selected'.
41  *
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  *
46  * Revision 1.4  1999/05/22 13:39:15  mdw
47  * Change spelling of `multiplexor'. ;-)
48  *
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  *
53  * Revision 1.2  1999/05/15 10:33:32  mdw
54  * Fix copyright notices.
55  *
56  * Revision 1.1  1999/05/14 21:01:15  mdw
57  * Integrated `select' handling bits from the background resolver project.
58  *
59  */
60
61 #ifndef MLIB_SEL_H
62 #define MLIB_SEL_H
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
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
118 enum {
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 */
123 };
124
125 typedef struct sel_state {
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 */
131 } sel_state;
132
133 /* --- Listening for a file --- */
134
135 typedef struct sel_file {
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 */
143   struct sel_pendfile *pend;            /* Pending file information */
144 } sel_file;
145
146 /* --- Waiting for a timeout --- */
147
148 typedef struct sel_timer {
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 */
154   struct sel_pendtimer *pend;           /* Pending timer information */
155 } sel_timer;
156
157 /* --- A select argument block --- */
158
159 typedef struct sel_args {
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 */
164 } sel_args;
165
166 /* --- A selector hook --- *
167  *
168  * The hooks are called (in arbitrary order) on each select.
169  */
170
171 typedef void (*sel_hookfn)(sel_state */*s*/,
172                            sel_args */*a*/,
173                            void */*p*/);
174
175 typedef struct sel_hook {
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 */
180 } sel_hook;
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
193 extern 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
211 extern 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
227 extern 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
238 extern void sel_rmfile(sel_file */*f*/);
239
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
252 extern void sel_force(sel_file */*f*/);
253
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
259  *              @void *p@ = argument for handler function
260  *
261  * Returns:     ---
262  *
263  * Use:         Registers and sets up a timer.
264  */
265
266 extern 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
281 extern void sel_rmtimer(sel_timer */*t*/);
282
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
295 extern 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
308 extern 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
322 extern int sel_fdmerge(fd_set */*dest*/, fd_set */*fd*/, int /*maxfd*/);
323
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
333 extern int sel_select(sel_state */*s*/);
334
335 /*----- That's all, folks -------------------------------------------------*/
336
337 #ifdef __cplusplus
338   }
339 #endif
340
341 #endif