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