A file-descr-watcher is essentially a map from File_descr.t
to bool
Read_write.t
, which defines the set of file descriptors being watched, and for each
file descriptor, whether it is being watched for read, write, or both. If a file
descriptor is not being watched for either, it is not in the map.
additional_create_args
abstracts over the additional arguments to different
file-descr-watcher's create
function.
create ~num_file_descrs
creates a new file-descr-watcher that is able to watch
file descriptors in
[0, num_file_descrs)
.
set
alters the map of file descriptors being watched. It will take effect on the
next call to thread_safe_check
. Calling set fd
with { read = false, write =
false }
removes fd
from the map.
iter t ~f
iterates over every file descriptor in the map, apply f
to it once
for each of {`Read,`Write} that it is being watched for.
pre_check t
does whatever non-thread-safe work is necessary to prepare for the
system call that checks file descriptors being ready for read or write.
thread_safe_check t pre timeout span_or_unit
checks the file descriptors for their
status and returns when at least one is available, or the timeout, span_or_unit
passes.
post_check t check_result
calls the handle_fd*
functions supplied to create
:
1. for each file descriptor that is ready to be written to, then 2. for each file descriptor that is ready to be read from.
We handle writes before reads so that we get all the writes started going to the external world before we process all the reads. This will nicely batch together all the output based on the reads for the next writes.
It is guaranteed that it calls handle_fd_read*
only on an fd
that is watched for
read as per set
, and handle_fd_write*
only on an fd
that is watched for write
as per set
.