On Apr 19, 2012, at 7:30 AM, Nick Mathewson wrote:
On Tue, Apr 10, 2012 at 7:21 PM, Nir Soffer <nir...@gmail.com> wrote:
On Apr 10, 2012, at 6:15 PM, Nick Mathewson wrote:
And there's a third way for libevent to see a big jump forward in
time: if the program calls event_base_loop() sporadically, it is
free
to wait as long as it wants between invocations.
So, what's the right behavior for periodic events in these cases?
If
there is an event that's supposed to run every 5 seconds, and time
has
jumped forward by 16 seconds, it seems reasonable to run the event 1
time, or maybe even 3 times... but if time has jumped forward by one
day, it seems unlikely that the programmer really wants us to run
the
event 17280 times.
Perhaps this argues for a cap on how far into the past we should be
willing to reschedule a periodic event, or how many "missed firings"
we'll compensate for before we drop some on the floor?
Forward jumps should simply skip events in the past. It is just
like events
skipped because the event loop was blocked.
If you should run every 5 seconds, but woke up 21 seconds late, you
cannot
fix the past - you just missed the events at +5, +10, +15 and +20.
Run the
next event at +25 according to the plan.
Other event loops like Cocoa NSRunloop and GNUStep NSRunloop use
this logic.
I've implemented approximately this logic in branch
"20_periodic_event_overload" in my github repository. (That's where I
do most of my work before merging it onto an official branch; it lives
at https://github.com/nmathewson/libevent .)
If I understand the code correctly, it does fix the unwanted loop, but
is also changes the schedule of the timer, which may be unwanted.
If the timer missed few events (ev_timeout + dealy < now) then the
next timeout (run_at) is now + delay.
So if we take the example of running every 5 seconds and then we miss
the 20 seconds event and wake up at 21, the current code will schedule
the next event at 26. Assuming that we have another delay at 42, the
total run may look like this:
5 10 15 21 26 31 42 47 ...
What I expect from such timer is to keep running according to the
original schedule when possible.
5 10 15 21 25 30 42 45 ...
Maybe it is not the best example for libevent, but lets say I'm
writing a clock that should play a tone on each hour. According to the
current code, after the first delay where I missed my deadline and
played the tone few seconds later, I will continue to miss the
deadline on each hour.
So a more correct implementation would be something like this
(assuming that all values are integers instead of timevals):
elapsed = now - ev->ev_timeout;
intervals = elapsed / delay + 1;
delta = intervals * delay;
run_at = ev->ev_timeout + delta;
I think that most users will prefer this logic. If I wanted to wait at
least 5 seconds after each run, I would use a non-persistent event,
adding the event with a timeout after each run.
What do you think?
***********************************************************************
To unsubscribe, send an e-mail to majord...@freehaven.net with
unsubscribe libevent-users in the body.