On Mon, Mar 29, 2010 at 12:36 PM, M P <buser...@gmail.com> 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 majord...@freehaven.net with unsubscribe libevent-users in the body.