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 small improvements to evhttp documentation
|
||||||
o always generate Date and Content-Length headers for HTTP/1.1 replies
|
o always generate Date and Content-Length headers for HTTP/1.1 replies
|
||||||
o set the correct event base for HTTP close events
|
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:
|
Changes in 1.4.0-beta:
|
||||||
|
@ -54,6 +54,7 @@ struct event_base {
|
|||||||
int event_count_active; /* counts number of active events */
|
int event_count_active; /* counts number of active events */
|
||||||
|
|
||||||
int event_gotterm; /* Set to terminate loop */
|
int event_gotterm; /* Set to terminate loop */
|
||||||
|
int event_break; /* Set to terminate loop immediately */
|
||||||
|
|
||||||
/* active event management */
|
/* active event management */
|
||||||
struct event_list **activequeues;
|
struct event_list **activequeues;
|
||||||
|
17
event.3
17
event.3
@ -34,10 +34,12 @@
|
|||||||
.Nm event_dispatch ,
|
.Nm event_dispatch ,
|
||||||
.Nm event_loop ,
|
.Nm event_loop ,
|
||||||
.Nm event_loopexit ,
|
.Nm event_loopexit ,
|
||||||
|
.Nm event_loopbreak ,
|
||||||
.Nm event_set ,
|
.Nm event_set ,
|
||||||
.Nm event_base_dispatch ,
|
.Nm event_base_dispatch ,
|
||||||
.Nm event_base_loop ,
|
.Nm event_base_loop ,
|
||||||
.Nm event_base_loopexit ,
|
.Nm event_base_loopexit ,
|
||||||
|
.Nm event_base_loopbreak ,
|
||||||
.Nm event_base_set ,
|
.Nm event_base_set ,
|
||||||
.Nm event_base_free ,
|
.Nm event_base_free ,
|
||||||
.Nm event_add ,
|
.Nm event_add ,
|
||||||
@ -93,6 +95,8 @@
|
|||||||
.Fn "event_loop" "int flags"
|
.Fn "event_loop" "int flags"
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn "event_loopexit" "struct timeval *tv"
|
.Fn "event_loopexit" "struct timeval *tv"
|
||||||
|
.Ft int
|
||||||
|
.Fn "event_loopbreak" "void"
|
||||||
.Ft void
|
.Ft void
|
||||||
.Fn "event_set" "struct event *ev" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg"
|
.Fn "event_set" "struct event *ev" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg"
|
||||||
.Ft int
|
.Ft int
|
||||||
@ -102,6 +106,8 @@
|
|||||||
.Ft int
|
.Ft int
|
||||||
.Fn "event_base_loopexit" "struct event_base *base" "struct timeval *tv"
|
.Fn "event_base_loopexit" "struct event_base *base" "struct timeval *tv"
|
||||||
.Ft int
|
.Ft int
|
||||||
|
.Fn "event_base_loopbreak" "struct event_base *base"
|
||||||
|
.Ft int
|
||||||
.Fn "event_base_set" "struct event_base *base" "struct event *"
|
.Fn "event_base_set" "struct event_base *base" "struct event *"
|
||||||
.Ft void
|
.Ft void
|
||||||
.Fn "event_base_free" "struct event_base *base"
|
.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
|
exit without blocking for events again. Subsequent invocations of
|
||||||
.Fn event_loop
|
.Fn event_loop
|
||||||
will proceed normally.
|
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
|
.Pp
|
||||||
It is the responsibility of the caller to provide these functions with
|
It is the responsibility of the caller to provide these functions with
|
||||||
pre-allocated event structures.
|
pre-allocated event structures.
|
||||||
|
26
event.c
26
event.c
@ -358,7 +358,7 @@ event_process_active(struct event_base *base)
|
|||||||
ncalls--;
|
ncalls--;
|
||||||
ev->ev_ncalls = ncalls;
|
ev->ev_ncalls = ncalls;
|
||||||
(*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg);
|
(*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg);
|
||||||
if (event_gotsig)
|
if (event_gotsig || base->event_break)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,6 +402,25 @@ event_base_loopexit(struct event_base *event_base, struct timeval *tv)
|
|||||||
event_base, 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 */
|
/* not thread safe */
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -433,6 +452,11 @@ event_base_loop(struct event_base *base, int flags)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (base->event_break) {
|
||||||
|
base->event_break = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* You cannot use this interface for multi-threaded apps */
|
/* You cannot use this interface for multi-threaded apps */
|
||||||
while (event_gotsig) {
|
while (event_gotsig) {
|
||||||
event_gotsig = 0;
|
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 *);
|
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.
|
Add a timer event.
|
||||||
|
@ -769,6 +769,42 @@ test_loopexit(void)
|
|||||||
cleanup_test();
|
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
|
void
|
||||||
test_evbuffer(void) {
|
test_evbuffer(void) {
|
||||||
|
|
||||||
@ -1275,6 +1311,7 @@ main (int argc, char **argv)
|
|||||||
test_immediatesignal();
|
test_immediatesignal();
|
||||||
#endif
|
#endif
|
||||||
test_loopexit();
|
test_loopexit();
|
||||||
|
test_loopbreak();
|
||||||
|
|
||||||
test_multiple_events_for_same_fd();
|
test_multiple_events_for_same_fd();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user