bidi_fd_watcher, bidi_fd_watcher_impl

    // Members of dasynq::event_loop<T> instantiation:

    class bidi_fd_watcher;

    template <class Derived> class bidi_fd_watcher_impl; // : public bidi_fd_watcher;


Brief: bidi_fd_watcher is a member type of the event_loop template class. It represents an event watcher for file-descriptor readiness events, similar to the fd_watcher type, but with certain event-loop backend details abstracted away. In particular, bidi_fd_watcher always allows watching for both input and output readiness using a single watcher. The bidi_fd_watcher class should not be subclassed directly; the bidi_fd_watcher_impl template provides a means for subclassing.





Details and Usage

Please read the usage details for the fd_watcher class as they generally also apply to bidi_fd_watcher.

A bidi_fd_watcher largely acts as two separate fd_watcher instances — one for input readiness and one for output readiness — controlled via a single object. The two halves can be enabled/disabled independently and, importantly, may be queued independently (meaning that their callbacks may be issued concurrently if multiple threads are used to poll the event loop). The rules for the manipulating each half is the same as for watchers in general, including that they must not be enabled while already queued or processing callbacks if the event loop could be polled from a second thread. See the event_loop documentation for details.

Subclassing bidi_fd_watcher

To specify callback behaviour, bidi_fd_watcher can be subclassed — however, it should not be directly subclassed; instead, use the bidi_fd_watcher_impl implementation wrapper template.

add_watch (#2)

// member of dasynq::event_loop<T>::bidi_fd_watcher
template <typename T>
static fd_watcher<event_loop_t> *add_watch(event_loop_t &eloop, int fd, int flags, T watch_hndlr)

This variant of the add_watch function can be used to create and register a dynamically-allocated fd_watcher. The first three parameters are the same as for add_watch(#1). The watch_hndlr parameter is a function or lambda of the form:

[](event_loop_t &eloop, int fd, int flags) -> rearm { ... }

It acts as the callback function for the generated watcher (for both input and output readiness events). The flags parameter will be set to either dasynq::IN_EVENTS or dasynq:OUT_EVENTS. The watcher will delete itself when it is removed from the event loop.

This function can throw std::system_error or std::bad_alloc on failure.


Brief: The bidi_fd_watcher_impl class provides a basis for implementing bidi_fd_watcher, using the "curiously recurring template pattern". Instead of subclassing bidi_fd_watcher directly, subclass an instantiation of bidi_fd_watcher_impl with the template parameter specified as the subclass itself. For example:

class my_watcher : public bidi_fd_watcher_impl<my_watcher>
    // ...

Details and Usage

The callback functions must be provided in the subclass and named read_ready and write_ready, with signatures compatible with the following:

rearm read_ready(event_loop_t & loop, int fd);
rearm write_ready(event_loop_t & loop, int fd);

The callback functions must be public, but need not be virtual. They will be called with the following parameters:

The return value specifies the rearm action. The action is performed independently for the input and output halves of the watcher. If the rearm::REMOVE action is returned by either callback function, the relevant callback is disabled and the watch (as a whole) will be de-registered once the other callback function also returns rearm::REMOVE (or the watcher is explicitly deregistered).

To deregister the watcher (disarming both callbacks) from inside either callback, the deregister function can be used; the callback function should then return rearm::REMOVED.

Note that, if the event queue is polled from multiple threads, both callbacks may be active simultaneously.

A bidi_fd_watcher_impl instantiation has no public or protected members, other than those inherited from bidi_fd_watcher, which it publicly derives from.