Change the semantics of timeouts in conjunction with EV_PERSIST; timeouts in that case will now repeat until deleted.

svn:r1032
This commit is contained in:
Niels Provos 2009-01-22 02:33:38 +00:00
parent 309fc7c4ad
commit 56ea4687a5
5 changed files with 52 additions and 2 deletions

View File

@ -139,7 +139,8 @@ Changes in current version:
o Refactor internal notify-main-thread logic to prefer eventfd to pipe, then pipe to socketpair, and only use socketpairs as a last resort.
o Try harder to pack all evbuffer reads into as few chains as possible, using readv/WSARecv as appropriate.
o New evthread_use_windows_threads() and evthread_use_pthreads() functions to set up the evthread callbacks with reasonable defaults.
o Change the semantics of timeouts in conjunction with EV_PERSIST; timeouts in that case will now repeat until deleted.
Changes in 1.4.0:
o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.
o demote most http warnings to debug messages

View File

@ -40,7 +40,9 @@ extern "C" {
/* mutually exclusive */
#define ev_signal_next _ev.ev_signal.ev_signal_next
#define ev_io_next _ev.ev_io.ev_io_next
#define ev_io_timeout _ev.ev_io.ev_timeout
/* used only by signals */
#define ev_ncalls _ev.ev_signal.ev_ncalls

24
event.c
View File

@ -146,6 +146,7 @@ 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 event_persist_closure(struct event_base *, struct event *ev);
static int evthread_notify_base(struct event_base *base);
@ -572,6 +573,15 @@ event_periodic_closure(struct event_base *base, struct event *ev)
(*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg);
}
static void
event_persist_closure(struct event_base *base, struct event *ev)
{
/* reschedule the persistent event if we have a timeout */
if (ev->ev_io_timeout.tv_sec || ev->ev_io_timeout.tv_usec)
event_add(ev, &ev->ev_io_timeout);
(*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)
{
@ -904,7 +914,12 @@ event_set(struct event *ev, evutil_socket_t fd, short events,
__func__);
ev->ev_closure = event_signal_closure;
} else {
ev->ev_closure = NULL;
if (events & EV_PERSIST) {
timerclear(&ev->ev_io_timeout);
ev->ev_closure = event_persist_closure;
} else {
ev->ev_closure = NULL;
}
}
min_heap_elem_init(ev);
@ -1127,6 +1142,13 @@ event_add_internal(struct event *ev, const struct timeval *tv)
if (res != -1 && tv != NULL) {
struct timeval now;
/*
* for persistent timeout events, we remember the
* timeout value and re-add the event.
*/
if (ev->ev_closure == event_persist_closure)
ev->ev_io_timeout = *tv;
/*
* we already reserved memory above for the case where we
* are not replacing an exisiting timeout.

View File

@ -88,6 +88,7 @@ struct event {
/* used for io events */
struct {
TAILQ_ENTRY (event) (ev_io_next);
struct timeval ev_timeout;
} ev_io;
/* used by signal events */

View File

@ -507,6 +507,29 @@ test_periodictimeout(void)
cleanup_test();
}
static void
test_persistent_timeout(void)
{
struct timeval tv;
struct event ev;
int count = 0;
setup_test("Periodic timeout via EV_PERSIST: ");
timerclear(&tv);
tv.tv_usec = 10000;
event_assign(&ev, global_base, -1, EV_TIMEOUT|EV_PERSIST,
periodic_timeout_cb, &count);
event_add(&ev, &tv);
event_dispatch();
event_del(&ev);
cleanup_test();
}
#ifndef WIN32
static void signal_cb(int fd, short event, void *arg);
@ -2310,6 +2333,7 @@ main (int argc, char **argv)
util_suite();
test_periodictimeout();
test_persistent_timeout();
/* use the global event base and need to be called first */
test_priorities(1);