[Contents] [index] [Help] [Retrace] [browse <] [Browse >]

As stated above, you can send I/O requests to a device synchronously or
asynchronously.  The choice of which to use is largely a function of your
application.

Synchronous requests use the doio() function.  doio() will not return
control to your application until the I/O request has been satisfied by
the device.  The advantage of this is that you don't have to monitor the
message port for the device reply because DoIO() takes care of all the
message handling.  The disadvantage is that your application will be tied
up while the I/O request is being processed, and should the request not
complete for some reason, DoIO() will not return and your application will
hang.

Asynchronous requests use the sendio() and beginio() functions.  both
return to your application almost immediately after you call them.  This
allows you to do other operations, including sending more I/O requests to
the device.  Note that any additional I/O requests you send must use
separate I/O request structures. Outstanding I/O requests are not
available for re-use until the device is finished with them.

    Do Not Touch!
    -------------
    When you use sendio() or beginio(), the i/o request you pass to
    the device and any associated data buffers should be considered
    read-only.  Once you send it to the device, you must not modify it
    in any way until you receive the reply message from the device or
    abort the request.

Sending multiple asynchronous I/O requests to a device can be tricky
because devices require them to be unique and initialized.  This means you
can't use an I/O request that's still in the queue, but you need the
fields which were initialized in it when you opened the device.  The
solution is to copy the initialized I/O request to another I/O request(s)
before sending anything to the device.

Regardless of what you do while you are waiting for an asynchronous I/O
request to return, you need to have some mechanism for knowing when the
request has been done.  There are two basic methods for doing this.

The first involves putting your application into a wait state until the
device returns the I/O request to the message port of your application.
You can use the waitio(), wait() or waitport() function to wait for the
return of the I/O request. It is important to note that all of the above
functions and also doio() may wait() on the message reply port's
mp_sigbit.  for this reason, the task that created the port must be the
same task the waits for completion of the I/O.  There are three ways to
wait:

      * waitio() not only waits for the return of the i/o request, it
        also takes care of all the message handling functions.  This is
        very convenient, but you can pay for this convenience: your
        application will hang if the I/O request does not return.

      * wait() waits for a signal to be sent to the message port.  it
        will awaken your task when the signal arrives, but you are
        responsible for all of the message handling.

      * waitport() waits for the message port to be non-empty.  it
        returns a pointer to the message in the port, but you are
        responsible for all of the message handling.

The second method to detect when the request is complete involves using
the checkio() function.  checkio() takes an i/o request as its argument
and returns an indication of whether or not it has been completed.  When
CheckIO() returns the completed indication, you will still have to remove
the I/O request from the message port.