Automatic file descriptor timeouts

It is possible to set up a timeout mechanism for reading or writing to a file descriptor object. An x::fdtimeout gets attached to a file descriptor transport, and in turn exports a file descriptor transport with a timeout facade. Reading and writing through the x::fdtimeout object reads and writes the attached file descriptor, with the timeout functionality, when it's enabled.

#include <x::fdtimeout.H>

x::fd fd;

x::fdtimeout fd_with_timeout(x::fdtimeout::create(fd));

x::istream i(fd_with_timeout->getistream());

// ...

fd_with_timeout->set_read_timeout(5);

std::string line;

std::getline(i, line);

// ...
try {
    fd_with_timeout->pubread(buffer, bufsize);
} catch (const x::exception &e) {
}

fd->cancel_read_timeout();

set_read_timeout() starts a timer. Its parameter is actually a x::timespec. Invoking pubread() directly or indirectly waits for either data to be available, or for the timer to expire. In this case, an input stream reads a line from the file descriptor, invoking its pubread() method.

If the timer expires before the file descriptor is readable, pubread() throws an exception. If the file descriptor's pubread() gets invoked directly, catch this exception to detect a timeout condition (as demonstrated in the given example).

Note

Formatted input and output stream operators catch all exceptions thrown by the underlying streambuf, and set the failed bit in the stream's state (which may rethrow a std::exception, if the stream object is configured to do so), causing std::getline() to return.

cancel_read_timeout() removes the read timeout from the file descriptor. set_write_timeout() and cancel_write_timeout() implement an equivalent timeout functionality for writing to the file descriptor.

Note

Timeouts do not get cleared automatically, after a succesful read or a write. They are more like a deadline. After the timeout expires, all subsequent reads and writes fail. The timeouts should be explicitly cleared, if they get installed for the benefit of a single read or a write attempt.

It is possible to set up a periodic read or a write timeout by specifying a byte count in addition to the timeout:

fd_with_timeout->set_read_timeout(8192, 15);

This example sets a 15 second timeout. A timer gets started. As soon as 8192 bytes are read, the timer gets restarted. The timer will continue to get re-started, every 8192 bytes, until it's cancelled by cancel_read_timeout().

fd_with_timeout->set_write_timeout(8192, 15);

This example sets up a write timeout with equivalent semantics.

Note

Only the behavior of pubread() and pubwrite() is affected by setting a read or a write timeout. Other methods are not affected (except indirectly, as the result of the file descriptor set to the non-blocking mode).