chiark / gitweb /
Add a slew of manual pages.
[mLib] / man / sel.3
diff --git a/man/sel.3 b/man/sel.3
new file mode 100644 (file)
index 0000000..c3e81ae
--- /dev/null
+++ b/man/sel.3
@@ -0,0 +1,258 @@
+.\" -*-nroff-*-
+.TH sel 3mLib "22 May 1999" mLib
+.SH NAME
+sel \- low level interface for waiting for I/O
+.SH SYNOPSIS
+.nf
+.B "#include <mLib/sel.h>"
+
+.BI "void sel_init(sel_state *" s );
+
+.BI "void sel_initfile(sel_state *" s ", sel_file *" f ,
+.BI "                  int " fd ", unsigned " mode ,
+.BI "                  void (*" func ")(int " fd ", unsigned " mode ", void *" p ),
+.BI "                  void *" p );
+.BI "void sel_addfile(sel_file *" f );
+.BI "void sel_rmfile(sel_file *" f );
+
+.BI "void sel_addtimer(sel_state *" s ", sel_timer *" t ,
+.BI "                  struct timeval *" tv ,
+.BI "                  void (*" func ")(struct timeval *" tv ", void *" p ),
+.BI "void sel_rmtimer(sel_timer *" t );
+
+.BI "int sel_select(sel_state *" s );
+.fi
+.SH "OVERVIEW"
+The
+.B sel
+subsystem provides a structured way of handling I/O in a non-blocking
+event-driven sort of a way, for single-threaded programs.  (Although
+there's no reason at all why multithreaded programs shouldn't use 
+.BR sel ,
+it's much less useful.)
+.PP
+The
+.B sel
+subsystem does no memory allocation, and has no static state.  All
+of its data is stored in structures allocated by the caller.  I'll
+explain how this fits in nicely with typical calling sequences below.
+.PP
+Although all the data structures are exposed in the header file, you
+should consider
+.BR sel 's
+data structures to be opaque except where described here, and not fiddle
+around inside them.  Some things may become more sophisticated later.
+.SH "IMPORTANT CONCEPTS"
+The system is based around two concepts:
+.I multiplexors
+and
+.IR selectors .
+.PP
+A
+.I selector
+is interested in some sort of I/O event, which might be something like
+`my socket has become readable', or `the time is now half past three on
+the third of June 2013'.  It has a handler function attached to it,
+which is called when the appropriate event occurs.  Some events happen
+once only ever; some events happen over and over again.  For example, a
+socket might become readable many times, but it's only half-past three
+on the third of June 2013 once.
+.PP
+When a selector is initialized, the caller describes the event the
+selector is interested in, and specifies which function should handle
+the event.  Also, it must specify an arbitrary pointer which is passed
+to the handler function when the event occurs.  This is typically some
+sort of pointer to instance data of some kind, providing more
+information about the event (`it's
+.I this
+socket that's become readable'), or what to do about it.
+.PP
+A multiplexor gathers information about who's interested in what.  It
+maintains lists of selectors.  Selectors must be added to a
+mulitplexor before the events they're interested in are actually watched
+for.  Selectors can be removed again when their events aren't
+interesting any more.  Apart from adding and removing selectors, you can
+.I select
+on a multiplexor.  This waits for something interesting to happen and
+then fires off all the selectors which have events waiting for them.
+.PP
+You can have lots of multiplexors in your program if you like.  You can
+only ask for events from one of them at a time, though.
+.PP
+There are currently two types of selector understood by the low-level
+.B sel
+system: file selectors and timer selectors.  These two types of
+selectors react to corresponding different types of events.  A file
+event indicates that a file is now ready for reading or writing.  A
+timer event indicates that a particular time has now passed (useful for
+implementing timeouts).  More sophisticated selectors can be constructed
+using
+.BR sel 's
+interface.  For examples, see
+.BR selbuf (3mLib)
+and
+.BR conn (3mLib).
+.SH "PROGRAMMING INTERFACE"
+A multiplexor is represented using the type
+.B sel_state
+defined in the
+.B <mLib/sel.h>
+header file.  Before use, a
+.B sel_state
+must be initialized, by passing it to the
+.B sel_init
+function.  The header file talks about `state blocks' a lot \- that's
+because it was written before I thought the word `multiplexor' was
+nicer.
+.PP
+File selectors are represented by the type
+.BR sel_file .
+The interface provides three operations on file selectors:
+initialization, addition to multiplexor, and removal from a
+multiplexor.  It's convenient to separate addition and removal from
+initialization because file selectors often get added and removed many
+times over during their lifetimes.
+.PP
+A file selector is initialized by the
+.B sel_initfile
+function.  This requires a large number of arguments:
+.TP
+.I s
+A pointer to the multiplexor with which the file selector will be
+associated.  This is stored in the selector so that the multiplexor
+argument can be omitted from later calls.
+.TP
+.I f
+Pointer to the file selector object to be initialized.
+.TP
+.I fd
+The file descriptor which the selector is meant to watch.
+.TP
+.I mode
+A constant describing which condition the selector is interested in.
+This must be one of the
+.B SEL_
+constants described below.
+.TP
+.I func
+The handler function which is called when the appropriate condition
+occurs on the file.  This function's interface is described in more
+detail below.
+.TP
+.I p
+An arbitrary pointer argument passed to
+.I func
+when it's called.  Beyond this, no meaning is attached to the value of
+the pointer.  If you don't care about it, just leave it as null.
+.PP
+The mode argument is one of the following constants:
+.TP
+.B SEL_READ
+Raise an event when the file is ready to be read from.
+.TP
+.B SEL_WRITE
+Raise an event when the file is ready to be written to.
+.TP
+.B SEL_EXC
+Raise an event when the file has an `exceptional condition'.
+.PP
+The constant
+.B SEL_MODES
+contains the number of possible file modes.  This is useful internally
+for allocating arrays of the right size.
+.PP
+The functions
+.B sel_addfile
+and
+.B sel_rmfile
+perform the addition and removal operations on file selectors.  They are
+passed only the actual selector object, since the selector already knows
+which multiplexor it's associated with.  A newly initialized file
+selector is not added to its multiplexor: this must be done explicitly.
+.PP
+The handler function for a file multiplexor is passed three arguments:
+the file descriptor for the file, a mode argument which descibes the
+file's new condition, and the pointer argument set up at initialization
+time.
+.PP
+The member
+.B fd
+of the
+.B sel_file
+structure is exported.  It contains the file descriptor in which the
+selector is interested.  You may not modify this value, but it's useful
+to be able to read it out \- it saves having to keep a copy.
+.PP
+Timer selectors are simpler.  There are only two operations provided on
+timer selectors: addition and removal.  Initialization is performed as
+part of the addition operation.
+.PP
+A timer selector is represented by an object of time
+.BR sel_timer .
+.PP
+The function
+.B sel_addtimer
+requires lots of arguments:
+.TP
+.I s
+Pointer to the multiplexor to which the selector is to be added.
+.TP
+.I t
+Pointer to the timer selector object being initialized and added.
+.TP
+.I tv
+A
+.B "struct timeval"
+object describing when the selector should raise its event.  This is an
+.I absolute
+time, not a relative time as required by the traditional
+.BR select (2)
+and
+.BR poll (2)
+system calls.
+.TP
+.I func
+A handler function to be called when the event occurs.  The function is
+passed the
+.I current
+time, and the arbitrary pointer passed to
+.B sel_addtimer
+as the
+.I p
+argument.
+.TP
+.I p
+A pointer passed to
+.I func
+when the timer event occurs.  Beyond this, the value of the pointer is
+not inspected.
+.PP
+The function
+.B sel_rmtimer
+removes a timer selector.  It is passed only the selector object.
+.PP
+Note that timer events are a one-shot thing.  Once they've happened, the
+timer selector is removed and the event can't happen again.  This is
+normally what you want.  Removing a timer is only useful (or safe!)
+before the timer event has been sent.
+.PP
+Finally, the function
+.B sel_select
+is passed a multiplexor object.  It waits for something interesting to
+happen, informs the appropriate selector handlers, and returns.  If
+everything went according to plan,
+.B sel_select
+returns zero.  Otherwise it returns -1, and the global variable
+.B errno
+is set appropriately.
+.SH "OTHER NOTES"
+Although the naming seems to suggest that this is all
+based around the BSD-ish
+.BR select (2)
+system call (and indeed it is), the interface is actually a good deal
+more general than that.  An implementation which worked off System V-ish
+.BR poll (2)
+instead would be fairly trivial to make, and would look just the same
+from the outside.
+.SH AUTHOR
+Mark Wooding, <mdw@nsict.org>