in io/epoll.cpp [118:170]
virtual int add_interest(Event e) override {
if (e.fd < 0)
LOG_ERROR_RETURN(EINVAL, -1, "invalid file descriptor ", e.fd);
if (unlikely(!e.interests))
return 0;
if (unlikely((size_t)e.fd >= _inflight_events.size()))
_inflight_events.resize(e.fd * 2);
e.interests &= EVENT_RWEO;
auto& entry = _inflight_events[e.fd];
auto eint = entry.interests & EVENT_RWEO;
int op;
if (!eint) {
eint = e.interests;
op = EPOLL_CTL_ADD;
} else {
if ((eint ^ e.interests) & ONE_SHOT)
LOG_ERROR_RETURN(EALREADY, -1, "conflicted ONE_SHOT flag");
auto intersection = e.interests & eint;
auto data = (entry.reader_data != e.data) * EVENT_READ |
(entry.writer_data != e.data) * EVENT_WRITE |
(entry.error_data != e.data) * EVENT_ERROR ;
if (intersection & data)
LOG_ERROR_RETURN(EALREADY, -1, "conflicted interest(s)");
eint |= e.interests;
op = EPOLL_CTL_MOD;
}
auto events = evmap.translate_bitwisely(eint);
if (likely(eint & ONE_SHOT)) {
events |= EPOLLONESHOT;
if (likely(op == EPOLL_CTL_MOD)) {
// This may falsely fail with errno == ENOENT,
// if the fd was closed and created again.
// We should suppress that specific error log
int ret = ctl(e.fd, op, events, ENOENT);
if (likely(ret == 0)) goto ok;
// in such cases, and `EPOLL_CTL_ADD` it again.
else if (ret > 0) op = EPOLL_CTL_ADD;
else /*if (ret < 0)*/ goto fail;
}
}
if (ctl(e.fd, op, events) < 0) { fail:
LOG_ERROR_RETURN(0, -1, "failed to add_interest()");
}
ok: entry.interests |= eint;
if (e.interests & EVENT_READ) entry.reader_data = e.data;
if (e.interests & EVENT_WRITE) entry.writer_data = e.data;
if (e.interests & EVENT_ERROR) entry.error_data = e.data;
return 0;
}