IO Loop (StumpWM Manual)

### 11.1 IO Loop ¶

StumpWM’s internal loop is implemented by a generic multiplexing I/O loop for listening to I/O events from multiple sources. The model is as follows:

An I/O multiplexer is represented as an object, with which I/O channels can be registered to be monitored for events when the I/O loop runs. An I/O channel is any object for which the generic functions IO-CHANNEL-IOPORT, IO-CHANNEL-EVENTS and IO-CHANNEL-HANDLE are implemented.

IO-CHANNEL-IOPORT, given an I/O multiplexer and an I/O channel, should return the underlying system I/O facility that the channel operates on. The actual objects used to represent an I/O facility depends on the Lisp implementation, operating system and the specific I/O loop implementation, but, for example, on Unix implementations they will likely be numeric file descriptors. The I/O loop implementation implements IO-CHANNEL-IOPORT methods for the facilities it understands (such as FD-STREAMs on SBCL), so user-implemented channels should simply call IO-CHANNEL-IOPORT recursively on whatever it operates on.

IO-CHANNEL-EVENTS, given an I/O channel, should return a list of the events that the channel is interested in. See the documentation for IO-CHANNEL-EVENTS for further details.

The I/O loop guarantees that it will check what events a channel is interested in when it is first registered, and also at any time the channel has been notified of an event. If the channel changes its mind at any other point in time, it should use the IO-LOOP-UPDATE function to notify the I/O loop of such changes. The I/O loop may very well also update spuriously at other times, but such updates are not guaranteed.

IO-CHANNEL-HANDLE is called by the I/O loop to notify a channel of an event.

An I/O multiplexer is created with a MAKE-INSTANCE call on the class of the desired multiplexer implementation. If the code using the multiplexer has no certain preferences on an implementation (which should be the usual case), the variable *DEFAULT-IO-LOOP* points to a class that should be generally optimal given the current Lisp implementation and operating system.

Given a multiplexer, channels can be registered with it using IO-LOOP-ADD, unregistered with IO-LOOP-REMOVE, and updated with IO-LOOP-UPDATE (as described above). Call IO-LOOP on the multiplexer to actually run it.

Variable: *default-io-loop* ¶

  The default I/O loop implementation. Should be generically optimal for the given LISP implementation and operating system.

Variable: *current-io-loop* ¶

  Dynamically bound to the I/O loop currently running, providing an easy way for event callbacks to register new channels.

Variable: *current-io-channel* ¶

  While processing an I/O channel, this variable is dynamically bound to the channel in question. This is provided primarily for error-handling code.

Function: io-channel-ioport io-loop channel ¶

  Returns the I/O facility operated on by CHANNEL, in a representation understood by IO-LOOP. CHANNEL may be either an I/O channel or an object representing an underlying I/O facility, such as a stream object. An I/O loop implementation should implement methods for any primitive I/O facilities that it can monitor for events, and abstract channels should return whatever IO-CHANNEL-IOPORT returns for the primitive facility that it operates on.

  An I/O channel may also return NIL to indicate that it is only interested in purely virtual events, such as :TIMEOUT or :LOOP.

Function: io-channel-events channel ¶

  Returns a list of events that CHANNEL is interested in. An event specification may be a simple symbol, or a list of a symbol and additional data for the event. Specific I/O loop implementations may implement additional events, but the following event specifications should be supported by all I/O loops:

  :READ – The channel will be notified when its I/O port can be read from without blocking.

  :WRITE – The channel will be notified when its I/O port can be written to without blocking.

  (:TIMEOUT TIME-SPEC) – TIME-SPEC is a point in time in the same units as from (GET-INTERNAL-REAL-TIME), at which point the channel will be notified. It is permissible for TIME-SPEC to be a real number of any representation, but the system does not guarantee any particular level of accuracy.

  :LOOP – The channel will be notifed for each iteration of the I/O loop, just before blocking for incoming events. This should be considered a hack to be avoided, but may be useful for certain libraries (such as XLIB).

  If, at any time, an empty list is returned, the channel is unregistered with the I/O loop.

  The I/O loop will check what events a channel is interested in when it is first registered with the loop, and whenever the channel has been notified of an event. If the channel changes its mind at any other point in time, it should use the IO-LOOP-UPDATE function to notify the I/O loop of such changes. The I/O loop may also update spuriously at any time, but such updates are not guaranteed.

Function: io-channel-handle channel event &key &allow-other-keys ¶

  Default Values:

        &allow-other-keys  nil

  Called by the I/O loop to notify a channel that an event has occurred. EVENT is the symbol corresponding to the event specification from IO-CHANNEL-EVENTS (that is, :READ, :WRITE, :TIMEOUT or :LOOP). A number of keyword arguments with additional data specific to a certain event may also be passed, but no such arguments are currently defined.

Function: io-loop-add io-loop channel ¶

  Add a channel to the given I/O multiplexer to be monitored.

Function: io-loop-remove io-loop channel ¶

  Unregister a channel from the I/O multiplexer.

Function: io-loop-update io-loop channel ¶

  Make the I/O loop update its knowledge of what events CHANNEL is interested in. See the documentation for IO-CHANNEL-EVENTS for more information.

Function: io-loop io-loop &key description &allow-other-keys ¶

  Default Values:

        description        nil
        &allow-other-keys  nil

  Run the given I/O multiplexer, watching for events on any channels registered with it. IO-LOOP will return when it has no channels left registered with it.