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