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