ev_prepare watcher awkwardness

Marc Lehmann schmorp at schmorp.de
Sun Apr 19 12:31:22 CEST 2015

On Sat, Apr 18, 2015 at 02:17:01PM +0200, Thilo Schulz <thilo at tjps.eu> wrote:
> For both, ev_check and ev_prepare watchers, you're feeding them into the
> pending queue just like the other events, instead of, for instance, sorting
> them by priority in a linked list and then executing them.

They are being sorted by priority, just like any other event, which is the
primary reason to do it this way: Not specialcasing them, but treating
them the same.

> However, it does impose a limitation on the possibilities to the end-user of
> your library, one that is not intuitively obvious to those who are
> not intimately familiar with the inner workings of your library.

That's why there is this thing called "documentation" - ev_prepare
watchers are a very advanced concept (and have various limitations), and
work if you use them for the documented purpose. If you want to use them
for another purpose, it's not too much to ask to read the documentation
more thoroughly.

> So I think this behaviour should at least be documented in the section
> for prepare watchers.

It's not behaviour that is specific to prepare watchers.

> > I think chances are high that you are using ev_prepare watchers for
> > something they were not meant for (integrating other event sources), and
> > likely, the awkwardness will go away once you stop doing that.
> Umm, I'm not doing that sort of thing.

From your other mail (that I read afterwards), it very much looks as if
you are - ev_prepare watchers are not meant to delay actions, that's what
idle watchers or timers are for.

> I stumbled over this problem when I wanted my program to shut down
> cleanly by stopping all watchers.  This way I get an indication when
> a watcher is still running even though it should not, by, well, the
> program just not quitting when it should :)

"This way" refers to what?

> have interdepencies, meaning:  Closing one module triggers the closing
> of another module. Now the module unloading may or may not be triggered
> by the ev_prepare watcher being called, it may or may not be triggered
> by a function inside that module. The point is: I simply don't know.
> That's when I hit this problem, the program blocked in the poll syscall
> even though it should have gone on unloading the next module.

That's because you are using the wrong watcher type - if you want to delay
unloading, a timer would be the simplest approach (other approaches are
possible, such as queuing an event manually).

> > And why would the be necessary? If ev_prepare is soon enough, then you
> > obviously don't have the requirement of doing it immediately.
> Yes, you are right for _this particular_ use case.

Exactly - do you have any other use cases?

> And for those use cases where the precision of ev_now() is
> sufficient. What about time critical code, where real time timestamps
> are of importance?

You completely lost me now, first, what do timestamps have to do with
anything, and second, ev_now gives you a real time timestamp of the same
or higher precision as other real time stamps.

> ev_idle makes no guarantee whatsoever how many event loop interations
> need to happen before it is first invoked, which is bad.

Actually, it's good, because that is what it is invented for.

The number of event loop iterations is important how?

> And using ev_timer really seems like abusing the timer watcher. Use
> 0.000000001 as start time? That looks very hackish to me.

Indeed, if you want the shortest possible delay, 0 would be simplest and most

> What I was writing was merely a suggestion, it would make it easier for
> libev users to unravel recursion inside a watcher, which is basically
> what I want to do here.

Can you define "recursion inside a watcher" more clearly?

> But yeah, I can always make the callback be a wrapper function in the
> main program.

You can do a lot of things, but if you want to keep it simple, to delay
an action for as short as possible, a timer is quite appropriate. You can
manually feed an event into the event queue on any watcher, in which case
it will likely be executed earlier, but for your problem, this seems like
horrible overkill.

As is the case with all your solutions: they are rather complicated, abuse
watchers for purposes they were not designed for, while not stating a
single reason why the most naive and simple solution, using a watcher type
designed for your problem, wouldn't qualify.

                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_              http://www.deliantra.net
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      schmorp at schmorp.de
      -=====/_/_//_/\_,_/ /_/\_\

More information about the libev mailing list