Redundant epoll_ctl with ev_io watcher

Marc Lehmann schmorp at
Sat Nov 7 18:00:16 CET 2015

On Fri, Nov 06, 2015 at 05:25:38PM +0300, Nick Zavaritsky <mejedi at> wrote:
> > I don't quite see why you couldn't reuse the I/O watcher? I also use
> > coroutines, and typically it is possible to reuse the watcher (for
> > performance reasons, it is basically always faster to reuse watchers).
> Technically, reusing is possible, though it will require a massive refactoring. And it will likely make the code somewhat more complicated. Probably it is the right thing to do anyway, but I would really like to research other options first.

Are you sure it requires massive refactoring? While it might of course be
true, a simple (dynamic) array with a busy bit should already do and catch
most cases. Also, you already have to know whether your fd has changed or
not, how do you do that? Is this implicit in the code using your coroutine

Also, you need to be clear on your goals - id you are ok with less
performance and simpler code, your goal is already reached, apparently.

> > You can do whatever you want as long as you don't complain later, however,
> > libev doesn't really have a concept of "watcher flags" that is exposed.
> So switching between (say) EV_READ and (EV_READ | EV_WRITE) mode is only *officially* possible via ev_io_set, right?


> It would be great if it was possible to switch modes without triggering the code that works around the problem of reused file descriptors. Though at the first glance it seams that going from EV_READ to (EV_READ | EV_WRITE) requires a syscall anyway, that is not necessary the case, please consider the following situations:

I am not convinved it would be so great. All your problems go away with a
more efficient architecture: encouraging slower solutions is great why

> (1) multiple watchers for the same fd in the same loop, it is still possible that the ‘union’ mode didn’t change after all;
> (2) redundant R->RW->R mode switching before doing the next event loop iteration (I’ve actually asked about this use case on the mail list quite a while ago).

For multiple watchers, this could indeed be optimised inside libev, maybe,
possibly. Yet again, it solves a problem that doesn't happen with typical
uses, and can be avoided by using a more efficient design for untypical

> I suggest adding a lighter version of ev_io_set that

I think that would complicate the API for users, without adding much
gain. I am not completely set in stone for this, but at the moment, your
argument, which I essentially understand as "I have a suboptimal design
to start with, so I want libev to waste some more efficiency and make it
harder to use by others, so my suboptimal design works a bit better".

It might be possible to implement some multiple-watcher optimisation with
minimal overhead, which I might consider (and will look at when I have time),
but in general, having yet another abstraction layer to deal with a problem
that can be solved more efficiently already is not something I see as a
worthy goal.

And in your case, if you have some generic coroutine layer somewhere, it would
seem especially reasonable to invest a bit of effort into making this as
efficient as 

> I would really like to reuse IO watchers if I could; however it is complicated — currently N coroutines can block waiting for the same object. We really depend on this feature. And we don’t know N beforehand.

You could either add a waiting list to the watcher, or use some busy bit and
flal back to a separate watcher if the "normal" one is in use. The later
should be fine unless it is common for many coroutines to wait for the same
fd, and if it is common, I relly question your design (what's the point of
many coroutines to wait for read and write?). If it's a coroutine waiting
for read and another for write, then you can have two watchers for that. Or a
waiting list.

And if it's just "in case" that you want to allow many coroutines to wait for
the same fd, then it wouldn't be common.

                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_    
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      schmorp at
      -=====/_/_//_/\_,_/ /_/\_\

More information about the libev mailing list