mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-10 13:04:23 -04:00
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:
parent
d582000e37
commit
eecd6932c7
@ -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:
|
||||
|
@ -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
17
event.3
@ -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
26
event.c
@ -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
29
event.h
@ -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.
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user