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;
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.
Members
Types
- event_loop_t — the event loop type that this watcher registers with.
Constructors
- bidi_fd_watcher — default constructor.
Functions
- (#1) void add_watch(event_loop_t &eloop, int fd, int flags, int inprio = DEFAULT_PRIORITY, int outprio = DEFAULT_PRIORITY) —
add a watch for the specified file descriptor. The flags argument specifies a combination of dasynq::IN_EVENTS and dasynq::OUT_EVENTS specifying which readiness events to initially enable. - (#2) template <typename T>
static bidi_fd_watcher *add_watch(event_loop_t &eloop, int fd, int flags, T watchHndlr) —
add a dynamically-allocated watch with the specified callback. See add_watch(#1). The watch is automatically deleted when removed. The watchHandlr should be a lambda of the form [](event_loop_t &eloop, int fd, int flags) -> dasynq::rearm or a compatible function object. See details below. - void add_watch_noemu(event_loop_t &eloop, int fd, int flags,
int inprio = DEFAULT_PRIORITY, int outprio = DEFAULT_PRIORITY) —
add a watch as per add_watcher, but without watch emulation for regular files. If the backend does not support the specified file descriptor, throws std::system_error rather than emulating readiness events. - void set_in_watch_enabled(event_loop_t &eloop, bool b) noexcept — enable or disable watching input readiness events.
- void set_out_watch_enabled(event_loop_t &eloop, bool b) noexcept — enable or disable watching output readiness events.
- void set_watches(event_loop_t &eloop, int newFlags) noexcept — enable/disable both input and output readiness watches at the same time. newFlags is a combination of dasynq::IN_EVENTS and dasynq::OUT_EVENTS which specifies which watches will be enabled (if not set, the corresponding watch is disabled).
- void deregister(event_loop_t &eloop) noexcept
— request removal from the event loop. - int get_watched_fd() — returns the file descriptor associated with this watcher
- virtual void watch_removed() noexcept — called when the watcher has been removed from the event loop.
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.
bidi_fd_watcher_impl
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 event_loop_t::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:
- loop — a reference to the event loop.
- fd — the file descriptor being watched, as specified at registration.
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.