ev_periodic like functionality for time intervals

Marc Lehmann schmorp at schmorp.de
Fri May 22 09:49:00 CEST 2015


On Wed, May 20, 2015 at 11:57:31PM +0200, Thilo Schulz <thilo at tjps.eu> wrote:
> > The most compatible/conceptually simple solution would be to simply have
> > a one-minute timer or so and check for the interval yourself, which might
> 
> Hmm, time jumps will only be the exception that I want to catch if they 
> happen. I still want to trigger on entering the interval as soon as possible, 
> so to have a second watcher, a timer watcher in addition to the periodic is a 
> bit ugly in my opinion.

No, this suggestion was really only having one ev_timer, and checking for
interval crossings inside, you wouldn't have an extra ev_periodic watcher:

   int on;

   timer_callback (...)
   {
      int hour = get_hour ();

      int new_on = hour < 10 || hour > 22;

      if (new_on != on)
        {
          on = new_on;
          state changed!
        }
  }

It's the simple hack that I wouldn't use if you use if you had many of
these.

> > A more advanced technique would be to run a periodic watcher in manual
> > reschedule mode. In that mode, a callback will be invoked whenever a time
> > jump is detected (teh callback is very limited in what it can do, check
> > the docs).
> 
> Oh. I didn't realize the reschedule callback for periodics is invoked every 
> time libev() detects a time jump, forwards or backwards. This was not 
> immediately clear to me from the documentation

Yes, it really isn't documented, and it wasn't on my mind when I designed
it, but it turns out to work that way and I can say I am rather pleased
that the design of libev lends itself to a reasonably clean solution.

The reschedule_cb WAS meant to be called at internal undocumented points
in time, it was NOT meant as a "potential time jump indicator" (mostly for
lack of prior art to me, as this periodic thing seems to be quite uniqaue to
libev, and lack of usage example).

However, I do think that documenting the reschedule callback as such a
hook (among other things) is probably the right thing.

We are in the process of discussing on how to formalise this in the
documentation, which is likely a bit difficult.

> Just out of curiosity, from my first email:
> > > I guess in the latter case, I will need to detect a time jump backwards
> > > by, for instance, comparing the return value of ev_now() with the return
> > > value of ev_now() from a previous event loop iteration in an ev_check
> > > watcher.
> 
> could this method still be used to detect jumps backwards (assuming the time 
> until an event triggers the next event loop iteration won't cancel out  this 
> jump backwards)?

I guess it could - ev_now returns a POSIX timestamp, and if the time is
set sufficiently far backwards, it will go lower than a previous ev_now
stamp.

The problem is that you'd have to check often enough to not miss one, so
if you don't want to be off more than a few minutes, you'd have to check
every few minutes.

> I guess there's not really a way to wake up poll() on a system time jump

Well, one theoretically portable method we are aware of is using a second
thread and use pthread_cond_timedwait on systems with clock selection
support, but we are not going to use an extra thread for that, and I am a
bit doubtful on systems actually implementing this as per the standard,
so, no :) A non-portable option would probably be Linux's timerfd.

> Another question:
> Assuming it is now
> 09:00
> I start a periodic to fire at
> 10:00
> then I set system time to
> 11:00

> on this jump the periodics still need to be rescheduled.
> You said something about a 60sec accuracy of libev for detecting time jumps. 
> Is there some internal ev_timer watcher waking up the event loop every 60sec 
> to catch this?

A timer of sorts, but not an ev_timer: libev checks for timejumps on every
iteration and simply limits itself to sleep no more than MAX_BLOCKTIME (59.743s).

It can also ignore time jumps less than 1s even under the best of
conditions (a monotonic clock is available), and can't guarantee to detect
timejumps smaller than MAX_BLOCKTIME without a monotonic clock.

Most of the glorious logic is in time_update btw.

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