From: Niels Provos Date: Sat, 3 May 2008 22:10:09 +0000 (+0000) Subject: support for periodic timeouts X-Git-Tag: release-2.0.1-alpha~337 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1d30750b1de39c25ff930d8a52e2f3228fac353b;p=libevent support for periodic timeouts svn:r762 --- diff --git a/ChangeLog b/ChangeLog index b3bc09cc..d5d7231f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -87,6 +87,7 @@ Changes in current version: o introduce evbuffer_reserve_space() and evbuffer_commit_space() to make processing in filters more efficient. o reduce system calls for getting current time by caching it. o separate signal events from io events; making the code less complex. + o support for periodic timeouts Changes in 1.4.0: o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr. diff --git a/event.c b/event.c index 740d8f08..729ac8f7 100644 --- a/event.c +++ b/event.c @@ -137,6 +137,7 @@ static void timeout_process(struct event_base *); static void timeout_correct(struct event_base *, struct timeval *); static void event_signal_closure(struct event_base *, struct event *ev); +static void event_periodic_closure(struct event_base *, struct event *ev); static void detect_monotonic(void) @@ -362,6 +363,13 @@ event_haveevents(struct event_base *base) return (base->event_count > 0); } +static void +event_periodic_closure(struct event_base *base, struct event *ev) +{ + event_add(ev, &ev->_ev.ev_periodic.tv_interval); + (*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg); +} + static void event_signal_closure(struct event_base *base, struct event *ev) { @@ -709,6 +717,16 @@ event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, shor return (0); } +void +evperiodic_assign(struct event *ev, struct event_base *base, + struct timeval *tv, void (*cb)(evutil_socket_t, short, void *), void *arg) +{ + event_assign(ev, base, -1, EV_TIMEOUT, cb, arg); + + ev->_ev.ev_periodic.tv_interval = *tv; + ev->ev_closure = event_periodic_closure; +} + struct event * event_new(struct event_base *base, evutil_socket_t fd, short events, void (*cb)(evutil_socket_t, short, void *), void *arg) { diff --git a/include/event2/event.h b/include/event2/event.h index b85bc496..840092cb 100644 --- a/include/event2/event.h +++ b/include/event2/event.h @@ -184,6 +184,22 @@ int event_base_loopexit(struct event_base *, struct timeval *); */ int event_base_loopbreak(struct event_base *); +/** + Define a periodic timer. + + Behaves like a timer only that it repeats at the specified interval. + To start this time, it needs to be added via event_add(). + + @param ev event struct to be modified + @param base the event base to which this event belongs + @param tv periodicity interval + @param cb callback function + @param arg argument that will be passed to the callback function +*/ + +void evperiodic_assign(struct event *ev, struct event_base *base, + struct timeval *tv, void (*cb)(int, short, void *), void *arg); + /** Define a timer event. diff --git a/include/event2/event_struct.h b/include/event2/event_struct.h index b85e4528..56e24077 100644 --- a/include/event2/event_struct.h +++ b/include/event2/event_struct.h @@ -104,6 +104,10 @@ struct event { /* Allows deletes in callback */ short *ev_pncalls; } ev_signal; + + struct { + struct timeval tv_interval; + } ev_periodic; } _ev; short ev_events; diff --git a/test/regress.c b/test/regress.c index 993fba54..a7321835 100644 --- a/test/regress.c +++ b/test/regress.c @@ -432,6 +432,43 @@ test_simpletimeout(void) cleanup_test(); } +static void +periodic_timeout_cb(int fd, short event, void *arg) +{ + int *count = arg; + + (*count)++; + if (*count > 5) { + test_ok = 1; + event_base_loopexit(global_base, NULL); + } +} + +static void +test_periodictimeout(void) +{ + struct timeval tv, tv_interval; + struct event ev; + int count = 0; + + setup_test("Periodic timeout: "); + + timerclear(&tv_interval); + tv_interval.tv_usec = 10000; + + tv.tv_usec = 0; + tv.tv_sec = 0; + evperiodic_assign(&ev, global_base, &tv_interval, + periodic_timeout_cb, &count); + event_add(&ev, &tv); + + event_dispatch(); + + event_del(&ev); + + cleanup_test(); +} + #ifndef WIN32 extern struct event_base *current_base; static void @@ -2044,6 +2081,8 @@ main (int argc, char **argv) test_evutil_strtoll(); + test_periodictimeout(); + /* use the global event base and need to be called first */ test_priorities(1); test_priorities(2); @@ -2091,6 +2130,7 @@ main (int argc, char **argv) test_combined(); test_simpletimeout(); + #ifndef WIN32 test_simplesignal(); test_immediatesignal();