3 .\" Manual for event-driven I/O core
5 .\" (c) 1999, 2001, 2005, 2007, 2009, 2023, 2024 Straylight/Edgeware
8 .\"----- Licensing notice ---------------------------------------------------
10 .\" This file is part of the mLib utilities library.
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.
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.
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,
27 .\"--------------------------------------------------------------------------
28 .so ../defs.man \" @@@PRE@@@
30 .\"--------------------------------------------------------------------------
31 .TH sel 3mLib "22 May 1999" "Straylight/Edgeware" "mLib utilities library"
44 .\"--------------------------------------------------------------------------
46 sel \- low level interface for waiting for I/O
48 .\"--------------------------------------------------------------------------
52 .B "#include <mLib/sel.h>"
57 .B " SEL_WRITE = ...,"
62 .B "typedef struct { ...\& } sel_state;"
63 .B "typedef struct { ...\& } sel_timer;"
64 .B "typedef struct { ...\& } sel_hook;"
73 .B " fd_set fd[SEL_MODES];"
74 .B " struct timeval tv, *tvp;"
75 .B " struct timeval now;"
78 .BI "typedef void (*sel_hookfn)(sel_state *" s ", sel_args *" a ", void *" p );
80 .BI "void sel_init(sel_state *" s );
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 ),
87 .BI "void sel_addfile(sel_file *" f );
88 .BI "void sel_force(sel_file *" f );
89 .BI "void sel_rmfile(sel_file *" f );
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 ),
96 .BI "void sel_rmtimer(sel_timer *" t );
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 ,
102 .BI "void sel_rmhook(sel_hook *" h );
104 .BI "int sel_fdmerge(fd_set *" dest ", fd_set *" fd ", int " maxfd );
106 .BI "int sel_select(sel_state *" s );
109 .\"--------------------------------------------------------------------------
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
118 it's much less useful.)
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.
126 Although all the data structures are exposed in the header file, you
129 data structures to be opaque except where described here, and not fiddle
130 around inside them. Some things may become more sophisticated later.
132 .\"--------------------------------------------------------------------------
133 .SH "IMPORTANT CONCEPTS"
135 The system is based around two concepts:
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.
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
157 socket that's become readable'), or what to do about it.
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
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.
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.
171 There are currently two types of selector understood by the low-level
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
180 interface. For examples, see
185 .\"--------------------------------------------------------------------------
186 .SH "PROGRAMMING INTERFACE"
189 A multiplexor is represented using the type
193 header file. Before use, a
195 must be initialized, by passing it to the
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
201 File selectors are represented by the type
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.
210 A file selector is initialized by the
212 function. This requires a large number of arguments:
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.
220 Pointer to the file selector object to be initialized.
223 The file descriptor which the selector is meant to watch.
226 A constant describing which condition the selector is interested in.
227 This must be one of the
229 constants described below.
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
237 An arbitrary pointer argument passed to
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.
242 The mode argument is one of the following constants:
245 Raise an event when the file is ready to be read from.
248 Raise an event when the file is ready to be written to.
251 Raise an event when the file has an `exceptional condition'.
255 contains the number of possible file modes. This is useful internally
256 for allocating arrays of the right size.
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.
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
274 will sometimes be useful while a
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.
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.
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.
295 A timer selector is represented by an object of time
300 requires lots of arguments:
303 Pointer to the multiplexor to which the selector is to be added.
306 Pointer to the timer selector object being initialized and added.
308 .BI "struct timeval " tv
309 When the selector should raise its event. This is an
311 time, not a relative time as required by the traditional
317 .BI "void (*" func ")(struct timeval *" tv ", void *" p )
318 A handler function to be called when the event occurs. The function is
321 time, and the arbitrary pointer passed to
330 when the timer event occurs. Beyond this, the value of the pointer is
335 removes a timer selector. It is passed only the selector object.
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.
343 Finally, the function
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,
349 returns zero. Otherwise it returns \-1, and the global variable
351 is set appropriately.
354 In order to interface other I/O multiplexing systems to this one, it's
357 functions which are called before and after each
363 registers a pair of hook functions. It is passed the pointer to the
364 multiplexor which is being hooked, the address of a
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
373 removes a pair of hooks given the address of the
375 structure which recorded their registration.
379 is passed three arguments:
382 A pointer to the multiplexor block. This probably isn't very useful,
386 A pointer to a block containing proposed arguments for, or results from,
388 The format of this block is described below.
391 A pointer argument set up in the call to
393 to provide the hook function with some context.
395 The argument block contains the following members:
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.
401 .B "fd_set fd[SEL_MODES]"
402 A file descriptor set for each of
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.
413 .B "struct timeval tv, *tvp"
416 call, these specify the time after which to return even if no files are
419 is null, there is no timeout, and
421 should wait forever if necessary. Otherwise
423 should contain the address of
427 should contain the timeout. After the
429 call, the contents of
433 .B "struct timeval now"
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
440 Hook functions may find the call
442 useful. Given two file descriptor sets
446 and a possibly overestimated highest file descriptor in
450 all of the descriptors set in
452 and returns an accurate file descriptor count as its result.
454 .\"--------------------------------------------------------------------------
457 Although the naming seems to suggest that this is all
458 based around the BSD-ish
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
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,
467 .\"--------------------------------------------------------------------------
476 .\"--------------------------------------------------------------------------
479 Mark Wooding, <mdw@distorted.org.uk>
481 .\"----- That's all, folks --------------------------------------------------