ev_prepare watcher awkwardness

Thilo Schulz thilo at tjps.eu
Sat Apr 18 14:18:01 CEST 2015


I'm going to merge the discussion into this thread now, as the subject has
turned out to have some more overlapping.

On Saturday 18 April 2015 08:49:19 you wrote:
> The problem is that ev_prepare watchers have a special purpose and special
> semantics - you can't do everything inside one. While you can make a hack
> that calls newly-added prepare watchers, the awkwardness, as you call it,
> remains (a prepare watcher callback *has* to be aware that is is a prepare
> callback, it's not a normal callback), but the rules have become more
> complex, which is a loss-loss situation to me.

Hm. I've now had a more thorough look at the code.
      if (expect_false (preparecnt))
          queue_events (EV_A_ (W *)prepares, preparecnt, EV_PREPARE);

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.
You probably have good reasons for doing it in this manner (cache-performance
reasons as I gather from a few mailing list posts).

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.
("Heck, I started a prepare watcher, the doc says it will be executed before
the poll syscall, why doesn't it do so????!!!111)

So I think this behaviour should at least be documented in the section
for 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. 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 :)

As I've said I am using the prepare watcher to unload modules, which may
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.

> 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. 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?

ev_idle makes no guarantee whatsoever how many event loop interations need to
happen before it is first invoked, which is bad.
And using ev_timer really seems like abusing the timer watcher. Use 0.000000001 as
start time? That looks very hackish to me.

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.

But yeah, I can always make the callback be a wrapper function in the main
Either for ev_prepare() which will then do its own event queueing, or
likewise for any watcher where I will want to execute after that watcher has

Beste Grüße,
Thilo Schulz

More information about the libev mailing list