implement periodic reschedule callbacks

master
Marc Alexander Lehmann 2007-11-08 00:44:17 +00:00
parent cc1e33fc2f
commit 02fdea7be3
2 changed files with 35 additions and 20 deletions

49
ev.c
View File

@ -962,7 +962,14 @@ periodics_reify (EV_P)
assert (("inactive timer on periodic heap detected", ev_is_active (w)));
/* first reschedule or stop timer */
if (w->interval)
if (w->reschedule_cb)
{
ev_tstamp at = ((WT)w)->at = w->reschedule_cb (w, rt_now + 0.0001);
assert (("ev_periodic reschedule callback returned time in the past", ((WT)w)->at > rt_now));
downheap ((WT *)periodics, periodiccnt, 0);
}
else if (w->interval)
{
((WT)w)->at += floor ((rt_now - ((WT)w)->at) / w->interval + 1.) * w->interval;
assert (("ev_periodic timeout in the past detected while processing timers, negative interval?", ((WT)w)->at > rt_now));
@ -985,19 +992,15 @@ periodics_reschedule (EV_P)
{
struct ev_periodic *w = periodics [i];
if (w->interval)
{
ev_tstamp diff = ceil ((rt_now - ((WT)w)->at) / w->interval) * w->interval;
if (fabs (diff) >= 1e-4)
{
ev_periodic_stop (EV_A_ w);
ev_periodic_start (EV_A_ w);
i = 0; /* restart loop, inefficient, but time jumps should be rare */
}
}
if (w->reschedule_cb)
((WT)w)->at = w->reschedule_cb (w, rt_now);
else if (w->interval)
((WT)w)->at += ceil ((rt_now - ((WT)w)->at) / w->interval) * w->interval;
}
/* now rebuild the heap */
for (i = periodiccnt >> 1; i--; )
downheap ((WT *)periodics, periodiccnt, i);
}
inline int
@ -1311,11 +1314,14 @@ ev_periodic_start (EV_P_ struct ev_periodic *w)
if (ev_is_active (w))
return;
assert (("ev_periodic_start called with negative interval value", w->interval >= 0.));
/* this formula differs from the one in periodic_reify because we do not always round up */
if (w->interval)
((WT)w)->at += ceil ((rt_now - ((WT)w)->at) / w->interval) * w->interval;
if (w->reschedule_cb)
((WT)w)->at = w->reschedule_cb (w, rt_now);
else if (w->interval)
{
assert (("ev_periodic_start called with negative interval value", w->interval >= 0.));
/* this formula differs from the one in periodic_reify because we do not always round up */
((WT)w)->at += ceil ((rt_now - ((WT)w)->at) / w->interval) * w->interval;
}
ev_start (EV_A_ (W)w, ++periodiccnt);
array_needsize (struct ev_periodic *, periodics, periodicmax, periodiccnt, (void));
@ -1343,6 +1349,13 @@ ev_periodic_stop (EV_P_ struct ev_periodic *w)
ev_stop (EV_A_ (W)w);
}
void
ev_periodic_again (EV_P_ struct ev_periodic *w)
{
ev_periodic_stop (EV_A_ w);
ev_periodic_start (EV_A_ w);
}
void
ev_idle_start (EV_P_ struct ev_idle *w)
{

6
ev.h
View File

@ -141,6 +141,7 @@ struct ev_periodic
EV_WATCHER_TIME (ev_periodic);
ev_tstamp interval; /* rw */
ev_tstamp (*reschedule_cb)(struct ev_periodic *w, ev_tstamp now); /* rw */
};
/* invoked when fd is either EV_READable or EV_WRITEable */
@ -298,7 +299,7 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent
#define ev_io_set(ev,fd_,events_) do { (ev)->fd = (fd_); (ev)->events = (events_); } while (0)
#define ev_timer_set(ev,after_,repeat_) do { (ev)->at = (after_); (ev)->repeat = (repeat_); } while (0)
#define ev_periodic_set(ev,at_,interval_) do { (ev)->at = (at_); (ev)->interval = (interval_); } while (0)
#define ev_periodic_set(ev,at_,ival_,res_) do { (ev)->at = (at_); (ev)->interval = (ival_); (ev)->reschedule_cb= (res_); } while (0)
#define ev_signal_set(ev,signum_) do { (ev)->signum = (signum_); } while (0)
#define ev_idle_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_prepare_set(ev) /* nop, yes, this is a serious in-joke */
@ -307,7 +308,7 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent
#define ev_io_init(ev,cb,fd,events) do { ev_watcher_init ((ev), (cb)); ev_io_set ((ev),(fd),(events)); } while (0)
#define ev_timer_init(ev,cb,after,repeat) do { ev_watcher_init ((ev), (cb)); ev_timer_set ((ev),(after),(repeat)); } while (0)
#define ev_periodic_init(ev,cb,at,interval) do { ev_watcher_init ((ev), (cb)); ev_periodic_set ((ev),(at),(interval)); } while (0)
#define ev_periodic_init(ev,cb,at,ival,res) do { ev_watcher_init ((ev), (cb)); ev_periodic_set ((ev),(at),(ival),(res)); } while (0)
#define ev_signal_init(ev,cb,signum) do { ev_watcher_init ((ev), (cb)); ev_signal_set ((ev), (signum)); } while (0)
#define ev_idle_init(ev,cb) do { ev_watcher_init ((ev), (cb)); ev_idle_set ((ev)); } while (0)
#define ev_prepare_init(ev,cb) do { ev_watcher_init ((ev), (cb)); ev_prepare_set ((ev)); } while (0)
@ -335,6 +336,7 @@ void ev_timer_again (EV_P_ struct ev_timer *w);
void ev_periodic_start (EV_P_ struct ev_periodic *w);
void ev_periodic_stop (EV_P_ struct ev_periodic *w);
void ev_periodic_again (EV_P_ struct ev_periodic *w);
void ev_idle_start (EV_P_ struct ev_idle *w);
void ev_idle_stop (EV_P_ struct ev_idle *w);