Event-driven programs need to be able to wait for any of a set of I/O events simultaneously, and then identify which channels can be read or written without blocking the process.
In SETL, the routine to do this is called select, after the select routine introduced in 4.3BSD Unix. It takes a tuple of up to three sets of file descriptors as one parameter, and an optional timeout value as another. The sets identify streams that may become (1) ready for reading, (2) ready for writing, and (3) ready to return an error indication. The last of these has no specific meaning within SETL, though the environment may assign some. The most typical call, with only a set of potentially readable file descriptors specified, is *
[ready] := select ([readfds], timeout);and the general case is *
[r_ready, w_ready, e_ready] := select ([readfds, writefds, errorfds], timeout);The result set ready or r_ready is a subset of readfds, and lists those streams from which something can be read without blocking. Note that this does not say how many characters can be read, and in fact zero is possible, such as when end-of-file is immediate. Similar considerations apply to output, although in practice, operating systems and networks may themselves buffer packets and allow a program to flush all its output long before the receiver is actually ready.
Furthermore, readfds may include file descriptors on which accept (Section 3.1.2 [A Server]) can be called without blocking, and pseudo-fd's for signal and timer streams (Section 2.4.2 [Timers]) when they have lines to deliver.
The timeout parameter, which is an integer number of milliseconds, can be omitted to specify an indefinite wait, or can be as low as 0 to effect ``polling''.
We will find in Chapters 3 [Internet Sockets] and 4 [WEBeye: A Case Study] that it is convenient to structure virtually every TCP/IP server as a loop around a select call.