o provide event_base_new() that does not set the current_base global
o bufferevent_write now uses a const source argument; report from Charles Kerr
o improve documentation on event_base_loopexit; patch from Scott Lamb
+ 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:
o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.
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;
.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 ,
.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
.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"
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.
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;
}
}
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
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;
*/
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.
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) {
test_immediatesignal();
#endif
test_loopexit();
+ test_loopbreak();
test_multiple_events_for_same_fd();