7 #include <system_error>
14 return direction ==
Direction::In ? fd.read_count() : fd.write_count();
28 _rules.push_back({fd.duplicate(), direction, callback, interest, cancel});
64 bool something_to_poll =
false;
67 for (
auto it = _rules.cbegin(); it != _rules.cend();) {
68 const auto &this_rule = *it;
69 if (this_rule.direction ==
Direction::In && this_rule.fd.eof()) {
72 it = _rules.erase(it);
76 if (this_rule.fd.closed()) {
78 it = _rules.erase(it);
82 if (this_rule.interest()) {
83 pollfds.push_back({this_rule.fd.fd_num(),
static_cast<short>(this_rule.direction), 0});
84 something_to_poll =
true;
86 pollfds.push_back({this_rule.fd.fd_num(), 0, 0});
92 if (not something_to_poll) {
98 if (0 ==
SystemCall(
"poll", ::poll(pollfds.data(), pollfds.size(), timeout_ms))) {
99 return Result::Timeout;
102 if (e.
code().value() == EINTR) {
109 for (
auto [it, idx] =
make_pair(_rules.begin(),
size_t(0)); it != _rules.end(); ++idx) {
110 const auto &this_pollfd = pollfds[idx];
112 const auto poll_error =
static_cast<bool>(this_pollfd.revents & (POLLERR | POLLNVAL));
114 throw runtime_error(
"EventLoop: error on polled file descriptor");
117 const auto &this_rule = *it;
118 const auto poll_ready =
static_cast<bool>(this_pollfd.revents & this_pollfd.events);
119 const auto poll_hup =
static_cast<bool>(this_pollfd.revents & POLLHUP);
120 if (poll_hup && this_pollfd.events && !poll_ready) {
125 it = _rules.erase(it);
131 const auto count_before = this_rule.service_count();
132 this_rule.callback();
135 if (count_before == this_rule.service_count() and this_rule.interest()) {
137 "EventLoop: busy wait detected: callback did not read/write fd and is still interested");
144 return Result::Success;
unsigned int service_count() const
Result
Returned by each call to EventLoop::wait_next_event.
void add_rule(const FileDescriptor &fd, const Direction direction, const CallbackT &callback, const InterestT &interest=[] { return true;}, const CallbackT &cancel=[] {})
Add a rule whose callback will be called when fd is ready in the specified Direction.
Result wait_next_event(const int timeout_ms)
Calls poll(2) and then executes callback for each ready fd.
Direction
Indicates interest in reading (In) or writing (Out) a polled fd.
@ In
Callback will be triggered when Rule::fd is readable.
A reference-counted handle to a file descriptor.
a tagged_error for syscalls
SystemCall("socketpair", ::socketpair(AF_UNIX, SOCK_STREAM, 0, fds.data()))