For Development HEAD DRAFTSearch (procedure/syntax/module):

9.30 gauche.selector - Simple dispatcher

Module: gauche.selector

This module provides a simple interface to dispatch I/O events to registered handlers, based on sys-select (see I/O multiplexing).

Class: <selector>

{gauche.selector} A dispatcher instance that keeps watching I/O ports with associated handlers. A new instance can be created by make method.

Method: selector-add! (self <selector>) port-or-fd proc flags

{gauche.selector} Add a handler proc to the selector. proc is called when port-or-fd, which should be a port object or an integer that specifies a system file descriptor, meets a certain condition specified by flags. flags must be a list of one or more of the following symbols.

r

Calls proc when data is available at port-or-fd to read.

w

Calls proc when port-or-fd is ready to be written.

x

Calls proc when an exceptional condition occurs on port-or-fd.

proc is called with two arguments. The first one is port-or-fd itself, and the second one is a symbol r, w or x, indicating the condition.

If a handler is already associated with port-or-fd under the same condition, the previous handler is replaced by proc.

Method: selector-delete! (self <selector>) port-or-fd proc flags

{gauche.selector} Deletes the handler entries that matches port-or-fd, proc and flags. One or more of the arguments may be #f, meaning “don’t care”. For example,

(selector-delete! selector the-port #f #f)

deletes all the handlers associated to the-port, and

(selector-delete! selector #f #f '(w))

deletes all the handlers waiting for writable condition.

Method: selector-select (self <selector>) :optional (timeout #f)

{gauche.selector} Dispatcher body. Waits for the conditions registered in self, and when it occurs, calls the associated handler. If the timeout argument is omitted or false, this method waits indefinitely. Alternatively you can give a timeout value, that can be a real number in microseconds, or a list of two integers that represents seconds and microseconds.

Returns the number of handlers called. Zero means the selector has been timed out.

It is safe to modify self inside handler. The change will be effective from the next call of selector-select

This is a simple example of "echo" server:

(use gauche.net)
(use gauche.selector)
(use gauche.uvector)

(define (echo-server port)
  (let ((selector (make <selector>))
        (server   (make-server-socket 'inet port :reuse-addr? #t)))

    (define (accept-handler sock flag)
      (let* ((client (socket-accept server))
             (output (socket-output-port client)))
        (selector-add! selector
                       (socket-input-port client :buffering #f)
                       (lambda (input flag)
                         (echo client input output))
                       '(r))))

    (define (echo client input output)
      (let ((str (read-uvector <u8vector> 4096 input)))
        (if (eof-object? str)
            (begin (selector-delete! selector input #f #f)
                   (socket-close client))
            (begin (write-uvector str output)
                   (flush output)))))

    (selector-add! selector
                   (socket-fd server)
                   accept-handler
                   '(r))
    (do () (#f) (selector-select selector))))


For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT