Okay, 7 years later I have a more convincing answer based on this article by Evan Klitzke.
Firstly, the reason I asked the question in the first place is the often mentioned performance advantage of epoll
compared to poll
/select
. The word goes that epoll
is asymptotically more efficient (O(1)) than poll
(O(N)).
What is not as widely known is that only edge-triggered epoll
is truly O(1), while level-trggered epoll
has same asymptotics of O(N). Indeed, level-triggered flavor has to go over the list of watched fds every time it is called to find ones that potentially has still more data pending. Edge-triggered variety can rely on signals in response to new bytes appearing in an fd.
It would be interesting to find out, how exactly a resumed thread finds out which fd woke it up, but it's certainly possible that this datum is passed through during epoll-triggered wake-up.
Obviously, poll
/select
cannot use edge-triggered epoll
as the semantics are different. As we saw, implementing with level-triggered epoll
wouldn't bring asymptotic performance benefits. And possibly, also negatively affect it if constant factors or constant terms are high (as they seem to be based on coarse benchmark that I did and quoted in another comment).
For more information, please read Blocking I/O, Nonblocking I/O, And Epoll.
poll
as a wrapper forepoll
would be incredibly complex and inefficient. You'd either have to set up a new epoll descriptor and configure it each time or you'd have to do painful comparison of the current poll set to the one already associated with the epoll descriptor. Yuck!