## 7.14 Concurrent Input and Output

Reading from or writing to a file descriptor may block, since buffers my be empty or resp. full. Thus calling `read` or `write` might block the whole Oz process. We therefor provide abstractions that allow concurrent access to file descriptors from within the C level.

We first declare an abstact type `OZ_IOHandler` which is a function expecting an integer and an arbitrary pointer:

`typedef int OZ_IOHandler(int, void *);`

The user can then use the following abstractions:

`OZ_registerReadHandler`

  > `void OZ_registerReadHandler(int fd,OZ_IOHandler fun,void *args)`

  Registers `fun` as a read handler for file descriptor `fd`. Any previously registered function will be overridden. When input gets available on `fd` then `fun(fd,args)` will be called by the Oz scheduler. The usage of `args` provides a way to pass arbitrary arguments to `fun`.

`OZ_unregisterRead`

  > `void OZ_unregisterRead(int fd)`

  Unregisters a previously registered read handler for file descriptor `fd`.

`OZ_registerWriteHandler`

  > `void OZ_registerWriteHandler(int fd,OZ_IOHandler fun,void *args)`

  Analogously to `OZ_registerReadHandler` for writing. `fun` is called as soon as the output buffer for `fd` gets empty.

`OZ_unregisterWrite`

  > `void OZ_unregisterWrite(int fd)`

  Unregisters a previously registered write handler for file descriptor `fd`.