Using 'task'

an interface to the 'select' system call
Are there any existing picoLisp functions for using the 'select' system call and doing asynchronous IO?

Yes. In fact, this is the basis of almost all activities in a typical application.

The main control structure is a list of file descriptors and expressions in the global '*Run', usually in combination with the interface function 'task'.

For example, if you want to listen on multiple ports:

   (for P (4001 4002 4003 4004)
      (task (port P)
         (when (accept @)
            (task @
               Sock @
               (in Sock
                  (if (rd)
                     (out Sock (eval @))
                     (task Sock)
                     (close Sock) ) ) ) ) ) )

This will listen on those four ports, and whenever a connection request arrives, it will install a new task on this socket. Then, whenever data arrives on that socket, it is taken as an 'exe' expression, and gets evaluated with the current output channel set to that socket. If EOF arrives instead, the connection is closed and the task un-installed.

I often use this mechanism for communication between different systems. For communication with a browser you would better use line instead of rd, and send HTML-data instead of (eval @).

Note that all this happens in the "background". You may still have some main loop in your program (or, if not, you will be dropped into the console ':' prompt). The "do nothing" main loop is wait, that's why the examples for applications often have a '-wait' on the command line.

There are endless ways to combine task with I/O functions. A simple "single shot" background task, accepting a request on port 4444, reading an expression, evaluating it and immediately closing the connection:

   (task (port 4444)
      (let? Sock (accept @)
         (in Sock (out Sock (eval (rd))))
         (close Sock) ) )

Or, a main loop keeping multiple connections open on port 4444:

   (setq P (port 4444))
      (task (listen P)
         (in (setq Sock @)
            (if (rd)
               (out Sock (eval @))
               (task Sock)
               (close Sock) ) ) ) )

19mar16   erik