from trunk:

Patch from Scott Lamb: Implement event_{base_}loopbreak.  Includes documentation and tests.  From sf.net Feature Request 1826546.


svn:r584
This commit is contained in:
Niels Provos 2007-12-12 06:26:07 +00:00
parent d582000e37
commit eecd6932c7
6 changed files with 109 additions and 2 deletions

View File

@ -10,6 +10,7 @@ Changes in current version:
o small improvements to evhttp documentation
o always generate Date and Content-Length headers for HTTP/1.1 replies
o set the correct event base for HTTP close events
o New function, event_{base_}loopbreak. Like event_loopexit, it makes an event loop stop executing and return. Unlike event_loopexit, it keeps subsequent pending events from getting executed. Patch from Scott Lamb
Changes in 1.4.0-beta:

View File

@ -54,6 +54,7 @@ struct event_base {
int event_count_active; /* counts number of active events */
int event_gotterm; /* Set to terminate loop */
int event_break; /* Set to terminate loop immediately */
/* active event management */
struct event_list **activequeues;

17
event.3
View File

@ -34,10 +34,12 @@
.Nm event_dispatch ,
.Nm event_loop ,
.Nm event_loopexit ,
.Nm event_loopbreak ,
.Nm event_set ,
.Nm event_base_dispatch ,
.Nm event_base_loop ,
.Nm event_base_loopexit ,
.Nm event_base_loopbreak ,
.Nm event_base_set ,
.Nm event_base_free ,
.Nm event_add ,
@ -93,6 +95,8 @@
.Fn "event_loop" "int flags"
.Ft int
.Fn "event_loopexit" "struct timeval *tv"
.Ft int
.Fn "event_loopbreak" "void"
.Ft void
.Fn "event_set" "struct event *ev" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg"
.Ft int
@ -102,6 +106,8 @@
.Ft int
.Fn "event_base_loopexit" "struct event_base *base" "struct timeval *tv"
.Ft int
.Fn "event_base_loopbreak" "struct event_base *base"
.Ft int
.Fn "event_base_set" "struct event_base *base" "struct event *"
.Ft void
.Fn "event_base_free" "struct event_base *base"
@ -419,7 +425,16 @@ given timer expires will complete normally (handling all queued events) then
exit without blocking for events again. Subsequent invocations of
.Fn event_loop
will proceed normally.
The parameter indicates the time after which the loop should terminate.
The
.Nm event_loopbreak
function exits from the event loop immediately.
.Fn event_loop
will abort after the next event is completed;
.Fn event_loopbreak
is typically invoked from this event's callback. This behavior is analogous
to the "break;" statement. Subsequent invocations of
.Fn event_loop
will proceed normally.
.Pp
It is the responsibility of the caller to provide these functions with
pre-allocated event structures.

26
event.c
View File

@ -358,7 +358,7 @@ event_process_active(struct event_base *base)
ncalls--;
ev->ev_ncalls = ncalls;
(*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg);
if (event_gotsig)
if (event_gotsig || base->event_break)
return;
}
}
@ -402,6 +402,25 @@ event_base_loopexit(struct event_base *event_base, struct timeval *tv)
event_base, tv));
}
/* not thread safe */
int
event_loopbreak(void)
{
return (event_base_loopbreak(current_base));
}
int
event_base_loopbreak(struct event_base *event_base)
{
if (event_base == NULL)
return (-1);
event_base->event_break = 1;
return (0);
}
/* not thread safe */
int
@ -433,6 +452,11 @@ event_base_loop(struct event_base *base, int flags)
break;
}
if (base->event_break) {
base->event_break = 0;
break;
}
/* You cannot use this interface for multi-threaded apps */
while (event_gotsig) {
event_gotsig = 0;

29
event.h
View File

@ -408,6 +408,35 @@ int event_loopexit(struct timeval *);
*/
int event_base_loopexit(struct event_base *, struct timeval *);
/**
Abort the active event_loop() immediately.
event_loop() will abort the loop after the next event is completed;
event_loopbreak() is typically invoked from this event's callback.
This behavior is analogous to the "break;" statement.
Subsequent invocations of event_loop() will proceed normally.
@return 0 if successful, or -1 if an error occurred
@see event_base_loopbreak(), event_loopexit()
*/
int event_loopbreak(void);
/**
Abort the active event_base_loop() immediately.
event_base_loop() will abort the loop after the next event is completed;
event_base_loopbreak() is typically invoked from this event's callback.
This behavior is analogous to the "break;" statement.
Subsequent invocations of event_loop() will proceed normally.
@param eb the event_base structure returned by event_init()
@return 0 if successful, or -1 if an error occurred
@see event_base_loopexit
*/
int event_base_loopbreak(struct event_base *);
/**
Add a timer event.

View File

@ -769,6 +769,42 @@ test_loopexit(void)
cleanup_test();
}
static void
break_cb(int fd, short events, void *arg)
{
test_ok = 1;
event_loopbreak();
}
static void
fail_cb(int fd, short events, void *arg)
{
test_ok = 0;
}
void
test_loopbreak(void)
{
struct event ev1, ev2;
struct timeval tv;
setup_test("Loop break: ");
tv.tv_sec = 0;
tv.tv_usec = 0;
evtimer_set(&ev1, break_cb, NULL);
evtimer_add(&ev1, &tv);
evtimer_set(&ev2, fail_cb, NULL);
evtimer_add(&ev2, &tv);
event_dispatch();
evtimer_del(&ev1);
evtimer_del(&ev2);
cleanup_test();
}
void
test_evbuffer(void) {
@ -1275,6 +1311,7 @@ main (int argc, char **argv)
test_immediatesignal();
#endif
test_loopexit();
test_loopbreak();
test_multiple_events_for_same_fd();