Hi!

Looks like I’ve let the ball fall on this one :)

Discussion summary: Each time ev_io_set is being called, libev will assume that 
this is potentially a new file descriptor.

Marc said it’s not ok to hack a watcher to disable this ev_io quirk when we 
know for sure that the descriptor is the old one.

A lightweight variant of ev_io_set to switch R,W,RW watcher modes was requested 
and denied.

I don’t intend to persist any further in hopes that Marc will change his mind 
:) Just a few observations though.

a) I believe that documentation permits moving ev_io watcher to a different 
event loop without doing ev_io_set first. The loop will mishandle the 
descriptor since ev_io_start in the previous event loop has cleared the special 
flag set by ev_io_set.

b) For a casual docs reader like myself it wasn’t obvious that multiple 
watchers for one descriptor should be used if switching between R,W,RW modes is 
desired. Probably a relevant example in the docs will help?

Regards.

> On 07 Nov 2015, at 20:00, Marc Lehmann <[email protected]> wrote:
> 
> On Fri, Nov 06, 2015 at 05:25:38PM +0300, Nick Zavaritsky <[email protected]> 
> 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
> layer?
> 
> 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?
> 
> Yes.
> 
>> 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
> exactly?
> 
>> (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
> uses.
> 
>> 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_              http://www.deliantra.net
>      ----==-- _       generation
>      ---==---(_)__  __ ____  __      Marc Lehmann
>      --==---/ / _ \/ // /\ \/ /      [email protected]
>      -=====/_/_//_/\_,_/ /_/\_\


_______________________________________________
libev mailing list
[email protected]
http://lists.schmorp.de/mailman/listinfo/libev

Reply via email to