I'm rather new to event based programming. I'm experimenting with epoll
's edge-mode which apparently only signals files which have become ready for read/write (as opposed to level-mode which signals all ready files, regardless of whether there were already ready, or just became ready).
What's not clear to me, is: in edge-mode, am I informed of readiness events that happen while I'm not epoll_wait
ing ? What about events on one-shot files that haven't been rearmed yet ?
To illustrate why I'm asking that, consider the following scenario:
- have 10 non-blocking sockets connected
- configure
epoll_ctl
to react when the sockets are ready for read, in edge-mode + oneshot :EPOLLET | EPOLLONESHOT | EPOLLIN
epoll_wait
for something to happen (reports max 10 events)- linux wakes my process and reports sockets #1 and #2 are ready
- I
read
and process data socket #1 (untilE_AGAIN
) - I
read
and process data socket #2 (untilE_AGAIN
) - While I'm doing that, a socket S receives data
- I processed all events, so I rearm the triggered files with
epoll_ctl
inEPOLL_CTL_MOD
mode, because of oneshot - my loop goes back to
epoll_wait
ing the next batch of events
Ok, so will the last epoll_wait
always be notified of the readiness of socket S ? Event if S is #1 (i.e. it's not rearmed) ?
First let's get a clear view of the system, you need an accurate mental model of how the system works. Your view of
epoll(7)
is not really accurate.The difference between edge-triggered and level-triggered is the definition of what exactly makes an event. The former generates one event for each action that has been subscribed on the file descriptor; once you consume the event, it is gone - even if you didn't consume all the data that generated such an event. OTOH, the latter keeps generating the same event over and over until you consume all the data that generated the event.
Here's an example that puts these concepts in action, blatantly stolen from
man 7 epoll
:In short, the fundamental difference is in the definition of "event": edge-triggered treats events as a single unit that you consume once; level-triggered defines the consumption of an event as being equivalent to consuming all of the data belonging to that event.
Now, with that out of the way, let's address your specific questions.
Yes, you are. Internally, the kernel queues up the interesting events that happened on each file descriptor. They are returned on the next call to
epoll_wait(2)
, so you can rest assured that you won't lose events. Well, maybe not exactly on the next call if there are other events pending and the events buffer passed toepoll_wait(2)
can't accommodate them all, but the point is, eventually these events will be reported.Again, you never lose events. If the file descriptor hasn't been rearmed yet, should any interesting event arise, it is simply queued in memory until the file descriptor is rearmed. Once it is rearmed, any pending events - including those that happened before the descriptor was rearmed - will be reported in the next call to
epoll_wait(2)
(again, maybe not exactly the next one, but they will be reported). In other words,EPOLLONESHOT
does not disable event monitoring, it simply disables event notification temporarily.Given what I said above, by now it should be pretty clear: yes, it will. You won't lose any event. epoll offers strong guarantees, it's awesome. It's also thread-safe and you can wait on the same epoll fd in different threads and update event subscription concurrently. epoll is very powerful, and it is well worth taking the time to learn it!