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