x::fdtimeout
also implements the concept of a file descriptor terminator. A file
descriptor terminator is a separate file descriptor object that's
attached to the primary file descriptor.
When the terminator file descriptor becomes readable, calls to
primary descriptor's
pubread
(),
pubwrite
(),
pubaccept
(), and
pubconnect
() methods
throw an exception:
x::fd socket, terminatefd; // ... socket->nonblock(true); x::fdtimeout socket_with_timeout(x::fdtimeout::create(socket)); socket_with_timeout->set_terminate_fd(terminatefd);
In this example, when terminatefd
becomes readable,
all subsequent attempts to read or write from
socket_with_timeout
throw an exception.
The same terminator file descriptor may be attached, using
set_terminate_fd
() to multiple file descriptors.
The primary
file descriptor must be placed in non-blocking mode for this
to work, however its pubread
() and
write
() will block until either the primary file
is readable or writable, or until the terminator file descriptor
becomes readable.
Use cancel_terminate_fd
() to remove a terminator
file descriptor.
Only the behavior of pubread
(),
pubwrite
(),
pubaccept
() and
pubconnect
is affected by attaching a terminator
file descriptor. Other methods are not affected (except indirectly,
as the result of the file descriptor set to the non-blocking
mode).
This is a convenient mechanism to shut down a multithreaded server. Each client socket connection is serviced by a separate thread, and a terminator file descriptor gets attached to each socket file descriptor. The terminator file descriptor is the read end of a pipe, or an event file descriptor. Closing a pipe, or posting an event, stops reading and writing to all active sockets, which presumably results in automatic termination of all threads.