[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [Libevent-users] Recuring timers
On Mon, Mar 29, 2010 at 12:36 PM, M P <buserror@xxxxxxxxx> wrote:
> Is there a way to install timers that are not one-shot ? currently I
> have to re-add the timer in the callback to make it restart, however,
> it creates obvious drift.
> I'm looking for a timer that restarts itself automatically...
If you're using Libevent 2.0.x, set the EV_PERSIST flag on the timer event.
If you're using Libevent 1.4.x or earlier, you'll have to fake it as
you describe above. If you care about drift, you could implement a
quick-and-dirty persistent timer system with something like the
following (completely untested!) code:
#if !defined(LIBEVENT_VERSION_NUMBER) || LIBEVENT_VERSION_NUMBER < 0x02000100
struct recurring_timer {
struct event ev;
struct timeval tv_scheduled;
struct timeval tv_interval;
void (*timer_cb)(int fd, short what, void *user_data);
void *user_data;
};
static void recurring_timer_cb(int fd, short what, void *arg)
{
struct recurring_timer *timer = arg;
struct timeval now, delta;
evutil_gettimeofday(&now, NULL);
/* pick the next time to run this event at based on its last scheduled
* time. This logic may or may not be what you want. */
do {
evutil_timeradd(&timer->tv_scheduled, &timer->tv_interval,
&timer->tv_scheduled);
} while (evutil_timercmp(&now, &timer->tv_scheduled, <));
/* delta = scheduled - now */
evutil_timersub(&timer->tv_scheduled, &now, &delta);
if (event_add(&timer->ev, &delta) < 0) {
/* handle this error */
}
/* Run the user's callback */
timer->timer_cb(-1, EV_TIMEOUT, timer->user_data);
}
void free_recurring_timer(struct recurring_timer *timer)
{
event_del(&timer->ev);
free(timer);
}
struct recurring_timer *new_recurring_timer(
struct event_base *base,
struct timeval *interval,
void (*user_cb)(int, short, void *),
void *user_data)
{
struct recurring_timer *timer;
if (!(timer = malloc(sizeof(*timer))))
return NULL;
evutil_gettimeofday(&timer->tv_scheduled, NULL);
evutil_timeradd(&timer->tv_scheduled, interval, &timer->tv_scheduled);
memcpy(&timer->tv_interval, interval, sizeof(*interval));
timer->timer_cb = user_cb;
timer->user_data = user_data;
event_set(&timer->ev, -1, 0, recurring_timer_cb, timer);
if (base)
event_base_set(base, &timer->ev);
if (event_add(&timer->ev, interval) < 0) {
free(timer);
return NULL;
}
return timer;
}
#else
/* Looks like we have Libevent 2.0. */
#define recurring_timer event
#define free_recurring_timer(timer) event_free(timer)
struct recurring_timer *new_recurring_timer(
struct event_base *base,
struct timeval *interval,
void (*user_cb)(evutil_socket_t, short, void *),
void *user_data)
{
struct event *ev;
if (!(ev=event_new(base, -1, EV_PERSIST, user_cb, user_data)))
return NULL;
if (!(event_add(ev, interval))) {
event_free(ev);
return NULL;
}
return ev;
}
#endif
--
Nick
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users in the body.