chiark / gitweb /
da55fe862ae2a73775f8237cc05c2df50e5c6983
[mLib] / sel / sel.3
1 .\" -*-nroff-*-
2 .TH sel 3 "22 May 1999" "Straylight/Edgeware" "mLib utilities library"
3 .SH NAME
4 sel \- low level interface for waiting for I/O
5 .\" @sel_init
6 .\" @sel_initfile
7 .\" @sel_addfile
8 .\" @sel_force
9 .\" @sel_rmfile
10 .\" @sel_addtimer
11 .\" @sel_rmtimer
12 .\" @sel_addhook
13 .\" @sel_rmhook
14 .\" @sel_fdmerge
15 .\" @sel_select
16 .SH SYNOPSIS
17 .nf
18 .B "#include <mLib/sel.h>"
19 .PP
20 .ta 2n
21 .B "enum {"
22 .B "    SEL_READ = ...,"
23 .B "    SEL_WRITE = ...,"
24 .B "    SEL_EXC = ...,"
25 .B "    SEL_MODES = ..."
26 .B "};"
27 .PP
28 .B "typedef struct { ...\& } sel_state;"
29 .B "typedef struct { ...\& } sel_timer;"
30 .B "typedef struct { ...\& } sel_hook;"
31 .PP
32 .B "typedef struct {"
33 .B "    int fd;"
34 .B "    ..."
35 .B "} sel_file;"
36 .PP
37 .B "typedef struct {"
38 .B "    int maxfd;"
39 .B "    fd_set fd[SEL_MODES];"
40 .B "    struct timeval tv, *tvp;"
41 .B "    struct timeval now;"
42 .B "} sel_args;"
43 .PP
44 .BI "typedef void (*sel_hookfn)(sel_state *" s ", sel_args *" a ", void *" p );
45 .PP
46 .BI "void sel_init(sel_state *" s );
47 .PP
48 .ta \w'\fBvoid sel_initfile('u
49 .BI "void sel_initfile(sel_state *" s ", sel_file *" f ,
50 .BI "   int " fd ", unsigned " mode ,
51 .BI "   void (*" func ")(int " fd ", unsigned " mode ", void *" p ),
52 .BI "   void *" p );
53 .BI "void sel_addfile(sel_file *" f );
54 .BI "void sel_force(sel_file *" f );
55 .BI "void sel_rmfile(sel_file *" f );
56 .PP
57 .ta \w'\fBvoid sel_addtimer('u
58 .BI "void sel_addtimer(sel_state *" s ", sel_timer *" t ,
59 .BI "   struct timeval *" tv ,
60 .BI "   void (*" func ")(struct timeval *" tv ", void *" p ),
61 .BI "   void *" p );
62 .BI "void sel_rmtimer(sel_timer *" t );
63 .PP
64 .ta \w'\fBvoid sel_addhook('u
65 .BI "void sel_addtimer(sel_state *" s ", sel_hook *" h ,
66 .BI "   sel_hookfn " before ", sel_hookfn " after ,
67 .BI "   void *" p );
68 .BI "void sel_rmhook(sel_hook *" h );
69 .PP
70 .BI "int sel_fdmerge(fd_set *" dest ", fd_set *" fd ", int " maxfd );
71 .PP
72 .BI "int sel_select(sel_state *" s );
73 .fi
74 .SH "OVERVIEW"
75 The
76 .B sel
77 subsystem provides a structured way of handling I/O in a non-blocking
78 event-driven sort of a way, for single-threaded programs.  (Although
79 there's no reason at all why multithreaded programs shouldn't use
80 .BR sel ,
81 it's much less useful.)
82 .PP
83 The
84 .B sel
85 subsystem does no memory allocation, and has no static state.  All
86 of its data is stored in structures allocated by the caller.  I'll
87 explain how this fits in nicely with typical calling sequences below.
88 .PP
89 Although all the data structures are exposed in the header file, you
90 should consider
91 .BR sel 's
92 data structures to be opaque except where described here, and not fiddle
93 around inside them.  Some things may become more sophisticated later.
94 .SH "IMPORTANT CONCEPTS"
95 The system is based around two concepts:
96 .I multiplexors
97 and
98 .IR selectors .
99 .PP
100 A
101 .I selector
102 is interested in some sort of I/O event, which might be something like
103 `my socket has become readable', or `the time is now half past three on
104 the third of June 2013'.  It has a handler function attached to it,
105 which is called when the appropriate event occurs.  Some events happen
106 once only ever; some events happen over and over again.  For example, a
107 socket might become readable many times, but it's only half-past three
108 on the third of June 2013 once.
109 .PP
110 When a selector is initialized, the caller describes the event the
111 selector is interested in, and specifies which function should handle
112 the event.  Also, it must specify an arbitrary pointer which is passed
113 to the handler function when the event occurs.  This is typically some
114 sort of pointer to instance data of some kind, providing more
115 information about the event (`it's
116 .I this
117 socket that's become readable'), or what to do about it.
118 .PP
119 A multiplexor gathers information about who's interested in what.  It
120 maintains lists of selectors.  Selectors must be added to a
121 mulitplexor before the events they're interested in are actually watched
122 for.  Selectors can be removed again when their events aren't
123 interesting any more.  Apart from adding and removing selectors, you can
124 .I select
125 on a multiplexor.  This waits for something interesting to happen and
126 then fires off all the selectors which have events waiting for them.
127 .PP
128 You can have lots of multiplexors in your program if you like.  You can
129 only ask for events from one of them at a time, though.
130 .PP
131 There are currently two types of selector understood by the low-level
132 .B sel
133 system: file selectors and timer selectors.  These two types of
134 selectors react to corresponding different types of events.  A file
135 event indicates that a file is now ready for reading or writing.  A
136 timer event indicates that a particular time has now passed (useful for
137 implementing timeouts).  More sophisticated selectors can be constructed
138 using
139 .BR sel 's
140 interface.  For examples, see
141 .BR selbuf (3)
142 and
143 .BR conn (3).
144 .SH "PROGRAMMING INTERFACE"
145 .SS "Multiplexors"
146 A multiplexor is represented using the type
147 .B sel_state
148 defined in the
149 .B <mLib/sel.h>
150 header file.  Before use, a
151 .B sel_state
152 must be initialized, by passing it to the
153 .B sel_init
154 function.  The header file talks about `state blocks' a lot \- that's
155 because it was written before I thought the word `multiplexor' was
156 nicer.
157 .PP
158 File selectors are represented by the type
159 .BR sel_file .
160 The interface provides three operations on file selectors:
161 initialization, addition to multiplexor, and removal from a
162 multiplexor.  It's convenient to separate addition and removal from
163 initialization because file selectors often get added and removed many
164 times over during their lifetimes.
165 .SS "File selectors"
166 A file selector is initialized by the
167 .B sel_initfile
168 function.  This requires a large number of arguments:
169 .TP
170 .BI "sel_state *" s
171 A pointer to the multiplexor with which the file selector will be
172 associated.  This is stored in the selector so that the multiplexor
173 argument can be omitted from later calls.
174 .TP
175 .BI "sel_file *" f
176 Pointer to the file selector object to be initialized.
177 .TP
178 .BI "int " fd
179 The file descriptor which the selector is meant to watch.
180 .TP
181 .BI "unsigned " mode
182 A constant describing which condition the selector is interested in.
183 This must be one of the
184 .B SEL_
185 constants described below.
186 .TP
187 .BI "void (*" func ")(int " fd ", unsigned " mode ", void *" p );
188 The handler function which is called when the appropriate condition
189 occurs on the file.  This function's interface is described in more
190 detail below.
191 .TP
192 .BI "void *" p
193 An arbitrary pointer argument passed to
194 .I func
195 when it's called.  Beyond this, no meaning is attached to the value of
196 the pointer.  If you don't care about it, just leave it as null.
197 .PP
198 The mode argument is one of the following constants:
199 .TP
200 .B SEL_READ
201 Raise an event when the file is ready to be read from.
202 .TP
203 .B SEL_WRITE
204 Raise an event when the file is ready to be written to.
205 .TP
206 .B SEL_EXC
207 Raise an event when the file has an `exceptional condition'.
208 .PP
209 The constant
210 .B SEL_MODES
211 contains the number of possible file modes.  This is useful internally
212 for allocating arrays of the right size.
213 .PP
214 The functions
215 .B sel_addfile
216 and
217 .B sel_rmfile
218 perform the addition and removal operations on file selectors.  They are
219 passed only the actual selector object, since the selector already knows
220 which multiplexor it's associated with.  A newly initialized file
221 selector is not added to its multiplexor: this must be done explicitly.
222 .PP
223 The handler function for a file multiplexor is passed three arguments:
224 the file descriptor for the file, a mode argument which describes the
225 file's new condition, and the pointer argument set up at initialization
226 time.
227 .PP
228 The function
229 .B sel_force
230 will sometimes be useful while a
231 .B sel_select
232 call (see below) is in progress.  It marks a file selector as being
233 ready even if it's not really.  This is most useful when dynamically
234 adding a write selector: it's likely that the write will succeed
235 immediately, so it's worth trying.  This will only work properly if
236 the write is non-blocking.
237 .PP
238 The member
239 .B fd
240 of the
241 .B sel_file
242 structure is exported.  It contains the file descriptor in which the
243 selector is interested.  You may not modify this value, but it's useful
244 to be able to read it out \- it saves having to keep a copy.
245 .SS "Timer selectors"
246 Timer selectors are simpler.  There are only two operations provided on
247 timer selectors: addition and removal.  Initialization is performed as
248 part of the addition operation.
249 .PP
250 A timer selector is represented by an object of time
251 .BR sel_timer .
252 .PP
253 The function
254 .B sel_addtimer
255 requires lots of arguments:
256 .TP
257 .BI "sel_state *" s
258 Pointer to the multiplexor to which the selector is to be added.
259 .TP
260 .BI "sel_timer *" t
261 Pointer to the timer selector object being initialized and added.
262 .TP
263 .BI "struct timeval " tv
264 When the selector should raise its event.  This is an
265 .I absolute
266 time, not a relative time as required by the traditional
267 .BR select (2)
268 and
269 .BR poll (2)
270 system calls.
271 .TP
272 .BI "void (*" func ")(struct timeval *" tv ", void *" p )
273 A handler function to be called when the event occurs.  The function is
274 passed the
275 .I current
276 time, and the arbitrary pointer passed to
277 .B sel_addtimer
278 as the
279 .I p
280 argument.
281 .TP
282 .BI "void *" p
283 A pointer passed to
284 .I func
285 when the timer event occurs.  Beyond this, the value of the pointer is
286 not inspected.
287 .PP
288 The function
289 .B sel_rmtimer
290 removes a timer selector.  It is passed only the selector object.
291 .PP
292 Note that timer events are a one-shot thing.  Once they've happened, the
293 timer selector is removed and the event can't happen again.  This is
294 normally what you want.  Removing a timer is only useful (or safe!)
295 before the timer event has been sent.
296 .SS "Performing I/O"
297 Finally, the function
298 .B sel_select
299 is passed a multiplexor object.  It waits for something interesting to
300 happen, informs the appropriate selector handlers, and returns.  If
301 everything went according to plan,
302 .B sel_select
303 returns zero.  Otherwise it returns \-1, and the global variable
304 .B errno
305 is set appropriately.
306 .SS "Hook functions"
307 In order to interface other I/O multiplexing systems to this one, it's
308 possible to register
309 .I hook
310 functions which are called before and after each
311 .BR select (2)
312 system call.
313 .PP
314 The function
315 .B sel_addhook
316 registers a pair of hook functions.  It is passed the pointer to the
317 multiplexor which is being hooked, the address of a
318 .B sel_hook
319 structure which will be used to record the hook information, the two
320 hook functions (either of which may be a null pointer, signifying no
321 action to be taken), and a pointer argument to be passed to the hook
322 functions.
323 .PP
324 The function
325 .B sel_rmhook
326 removes a pair of hooks given the address of the
327 .B sel_hook
328 structure which recorded their registration.
329 .PP
330 A
331 .I "hook function"
332 is passed three arguments:
333 .TP
334 .BI "sel_state *" s
335 A pointer to the multiplexor block.  This probably isn't very useful,
336 actually.
337 .TP
338 .BI "sel_args *" a
339 A pointer to a block containing proposed arguments for, or results from,
340 .BR select (2).
341 The format of this block is described below.
342 .TP
343 .BI "void *" p
344 A pointer argument set up in the call to
345 .B sel_addhook
346 to provide the hook function with some context.
347 .PP
348 The argument block contains the following members:
349 .TP
350 .B "int maxfd"
351 One greater than the highest-numbered file descriptor to be examined.
352 This may need to be modified if the file descriptor sets are altered.
353 .TP
354 .B "fd_set fd[SEL_MODES]"
355 A file descriptor set for each of
356 .BR SEL_READ ,
357 .B SEL_WRITE
358 and
359 .BR SEL_EXC .
360 Before the
361 .B select
362 call, these may be modified to register an interest in other file
363 descriptors.  Afterwards, they may be examined to decide which file
364 descriptors are active.
365 .TP
366 .B "struct timeval tv, *tvp"
367 Before the
368 .B select
369 call, these specify the time after which to return even if no files are
370 active.  If
371 .B tvp
372 is null, there is no timeout, and
373 .B select
374 should wait forever if necessary.  Otherwise
375 .B tvp
376 should contain the address of
377 .BR tv ,
378 and
379 .B tv
380 should contain the timeout.  After the
381 .B select
382 call, the contents of
383 .B tv
384 are undefined.
385 .TP
386 .B "struct timeval now"
387 Before the
388 .B select
389 call, contains the current time.  After the call, this will have been
390 updated to reflect the new current time only if there was a timeout
391 set before the call.
392 .PP
393 Hook functions may find the call
394 .B sel_fdmerge
395 useful.  Given two file descriptor sets
396 .I dest
397 and
398 .IR fd ,
399 and a possibly overestimated highest file descriptor in
400 .IR fd ,
401 the function sets in
402 .I dest
403 all of the descriptors set in
404 .I fd
405 and returns an accurate file descriptor count as its result.
406 .SH "OTHER NOTES"
407 Although the naming seems to suggest that this is all
408 based around the BSD-ish
409 .BR select (2)
410 system call (and indeed it is), the interface is actually a good deal
411 more general than that.  An implementation which worked off System V-ish
412 .BR poll (2)
413 instead would be possible to make, and would look just the same from the
414 outside.  Some work would be needed to make the hook functions work,
415 though.
416 .SH "SEE ALSO"
417 .BR select (2),
418 .BR poll (2),
419 .BR conn (3),
420 .BR selbuf (3),
421 .BR mLib (3).
422 .SH AUTHOR
423 Mark Wooding, <mdw@distorted.org.uk>