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