asynchio,  asyn_init,  asyn_read,  asyn_read,   asyn_write,   asyn_ioctl,
     asyn_wait, asyn_synch - asynchronous I/O

     #include <fcntl.h>
     #include <time.h>
     #include <sys/asynchio.h>

     void asyn_init(asynchio_t *asyn)
     ssize_t asyn_read(asynchio_t *asyn, int fd, void *buf, size_t len)
     ssize_t asyn_write(asynchio_t *asyn, int fd, const void *buf, size_t len)
     int asyn_ioctl(asynchio_t *asyn, int fd, ioreq_t request, void *data)
     int asyn_wait(asynchio_t *asyn, int flags, struct timeval *to)
     int asyn_cancel(asynchio_t *asyn, int fd, int op)
     int asyn_pending(asynchio_t *asyn, int fd, int op)
     int asyn_synch(asynchio_t *asyn, int fd)
     int asyn_close(asynchio_t *asyn, int fd)

     These routines make asynchronous  I/O  programming  easier.   Instead  of
     starting several operations (that may or may not succeed) and waiting for
     them with fwait(2), one  programs  a  loop  around  several  asyn_read(),
     asyn_write(),  or  asyn_ioctl()  calls.   One  call to asyn_wait() blocks
     waiting for one or more  of  the  operations  to  succeed.   Results  are
     returned by the I/O operations themselves, not by asyn_wait().

     Asyn_init() initializes the bookkeeping structure needed  to  hold  flags
     and results.  This call is not needed on globally allocated structures.

     Asyn_read(), asyn_write(), asyn_ioctl() can be used just like the  normal
     read,  write and ioctl system calls in asynchronous mode, except that you
     can recall them until they return a result.   The  file  descriptor  flag
     FD_ASYNCHIO is set on the first call.

     Asyn_wait() uses fwait() to wait for one or more  of  the  operations  to
     finish.    It  gathers  all  results  that  fwait  has  available  before
     returning.  It will only block if all the operations are in progress,  so
     you  will  have  to  put a loop around everything.  Use the ASYN_NONBLOCK
     flag for a nonblocking call.  This flag may or may  not  cause  an  error
     return  with  errno  set  to  EAGAIN.   This depends on whether fwait was
     actually called.  This is how the routine works, either it simply returns
     0  (no fwait called), or it will return like fwait.  You can use a signal
     to end the wait, or you can use a  non-null  to  argument  to  specify  a
     timeout.  (An absolute time, not a time difference.)

     Asyn_synch() puts the file descriptor back  into  synchronous  mode,  and
     removes  it  from the bookkeeping.  It will fail with the EAGAIN error if
     there is still an operation in progress.

     Asyn_cancel() cancels a specific operation (use ASIO_READ, ASIO_WRITE  or
     ASIO_IOCTL for the operation code).  With asyn_pending() one can check if
     a result is available for a given operation.  Use it after  asyn_cancel()
     to  check  if  the  cancel  was  too  late, so that a result can still be
     obtained with one of  the  asyn_read/write/ioctl  calls.   Asyn_pending()
     returns  0  for  no  result, 1 for a result, and -1 for the unlikely case
     that the file descriptor is invalid.

     Asyn_close() only removes the bookkeeping on a file descriptor, the  file
     descriptor stays in asynchronous mode and there are no checks.

     This is how the functions may be used:

          asynchio_t asyn;
          len2= fill2(buf2);
          while (1) {
              if ((r= asyn_read(&asyn, fd1, buf1, len1)) != -1) {
                  use1(buf, r);
              } else {
                  if (errno != EINPROGRESS) disaster1();
              if ((r= asyn_write(&asyn, fd2, buf2, len2)) != -1) {
                  len2= fill2(buf2);
              } else {
                  if (errno != EINPROGRESS) disaster2();
              if (asyn_wait(&asyn, 0, NULL) == -1) {
                  if (errno == EINTR) timeout();

     Typical "back to synch" code for a read operation:

          if (asyn_cancel(&asyn, fd1, ASIO_READ) == -1) disaster4();
          if (asyn_pending(&asyn, fd1, ASIO_READ)) {
              r= asyn_read(&asyn, fd1, buf1, len1);
          if (asyn_synch(&asyn, fd1) == -1) disaster5();

     fwait(2), fcntl(2), read(2), write(2), ioctl(2).

     Kees J. Bot (