Alexey, On Fri, Jun 03, 2011 at 11:15:08AM +0400, Alexey Borzenkov wrote: > On Fri, Jun 3, 2011 at 2:34 AM, Marc Lehmann <[email protected]> wrote: > > Why would anybody want to use specifically a 0-second timer (where the 0 > > isn't just the chance result of some calculation)? > > > > The only reason I can know from past experience is that some people try > > to abuse 0-second timers as some replacement for idle watchers, possibly > > because that hack was the only way to get some kind of idle behaviour with > > some other event loop. > > No, it's not about idle at all. Imagine a massively concurrent system > where most coroutines are handling the network, but some occasionally > need to do a rather long/complex computation.
I have a similar project (namely Continuation Passing C) and, having considered those issues for some time, I beg to disagree. > If those coroutines don't want to block other coroutines from doing anything > useful, they need to yield as frequently as they can, and convenient way to > do it is using sleep(0). Idle wouldn't do a job here, Yes it does. At least I use it for that purpose without any trouble. > because if other coroutines are busy with network or timers or anything else, > idle callbacks won't be called and computation will halt. You just need to use idle workers with a higher priority than your io and timers. > Also, ev_check won't work here, ev_check might not work in the general case indeed, but for a very different reason: if your busy coroutine is the only one left (ie. no network activity), the loop will exit --- unless I am mistaken, a check worker is not enough to let the loop continue. > because on the next iteration this callback will be called first, it might > not have given other coroutines a chance to work yet, High priority idle watchers work that way, and I believe this is not an issue. Any long running computation will call "yield" (or sleep(0) in your case) often so even if it is invoked "too early" (before io watchers), you are just offsetting your computation by a time-slice. I understand this is not exactly the same semantics, but I fail to see why one would be suitable when the other is not. > besides as far as I understand ev_check doesn't influence poll timeout. I believe we agree on that point. > Immediate timers seem to be the only primitive that has necessary properties: > > - needs to make sure backend_poll() is called If you have active io watchers, poll should be called anyway. > - needs to make sure any pending io is processed They will be processed (only later, but then again this should not be an issue --- in case it really is, just define "yield" to yield twice in a row). > - needs to make sure backend_poll() doesn't sleep Idle watchers with high priority prevent that. > - needs to make sure it is called as soon as possible after io is processed Define io watchers with lowest priority and idle watchers with highest. You'll have io watchers executed at the end of your loop turn, followed by a new call to poll and then your idle watchers. > and preferable in order fair to others I don't know exactly what you mean by fairness but I agree this is a weakness of libev (I sent a mail recently about it): if you want to ensure deterministic scheduling among some event (eg. have the idle watchers for a given priority executed in the same order they were started), you need to roll your own queue. But I perfectly understand Marc's reasons. > Currently ev_timer with timeout of 0.0, sadly, doesn't satisfy all > these properties. However, ev_timer with timeout of -1.0, or any big > enough negative timeout, does. > > P.S. Of course the proper way to handle these computations is to use a > thread pool and offload computation tasks there. It's actually what I > ended up doing in one of my systems and it works a lot better than > yielding. Same conclusion here :-) Best regards, -- Gabriel _______________________________________________ libev mailing list [email protected] http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
