如何打破 libevent 的调度循环
How to break out libevent's dispatch loop
我使用漂亮的 libevent 库在单独的线程中实现了一个小型网络服务器。网络服务器 运行s event_base_dispatch() 处理所有事件。我需要的是一种从主线程中打破这个调度循环的方法。
它归结为以下 C++ 代码:
#include <stdlib.h>
#include <signal.h>
#include <thread>
#include <evhttp.h>
struct event_base *eb;
std::thread t;
static volatile sig_atomic_t bailout = false;
void my_signal_handler(int) {
bailout = true;
}
void onRequest(evhttp_request *req, void *) {
struct evbuffer *OutBuf = evhttp_request_get_output_buffer(req);
evbuffer_add_printf(OutBuf, "<html><body>Testing 1-2-3</body></html>");
evhttp_send_reply(req, HTTP_OK, "OK", OutBuf);
}
void dispatch() {
eb = event_base_new();
struct evhttp *http = evhttp_new(eb);
evhttp_set_gencb(http, &onRequest, NULL);
evhttp_bind_socket_with_handle(http, "0.0.0.0", 5555);
event_base_dispatch(eb);
}
int main() {
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = my_signal_handler;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
t = std::thread { &dispatch };
while ( ! bailout ) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
event_base_loopexit(eb, NULL);
t.join();
}
行为是,如果您 运行 程序,请求页面,按 Ctrl-C 中止程序,event_base_dispatch() 保持 运行ning 直到 你获取另一个网页。只有这样循环才会中止并且程序终止。
如果您需要在 运行 任何更多回调之前退出事件循环,请使用 event_base_break()
http://www.wangafu.net/~nickm/libevent-book/Ref3_eventloop.html#_stopping_the_loop
最后我通过添加一个基本上轮询 bailout 变量的计时器来实现打破调度循环:
struct event *ev;
const struct timeval one_sec = { 1, 0 }; // sec, usec
void cb_timer_func(evutil_socket_t, short, void) {
if ( bailout ) {
event_base_loopbreak(eb);
}
else if ( ! evtimer_pending(ev, NULL) ) {
evtimer_del(ev);
evtimer_add(ev, &one_sec);
}
}
并且在调度循环中,我添加了:
ev = evtimer_new(eb, cb_timer_func);
evtimer_add(ev, &one_sec);
另一种方法是将 event_base_loopbreak()
放入信号处理程序。
我使用漂亮的 libevent 库在单独的线程中实现了一个小型网络服务器。网络服务器 运行s event_base_dispatch() 处理所有事件。我需要的是一种从主线程中打破这个调度循环的方法。
它归结为以下 C++ 代码:
#include <stdlib.h>
#include <signal.h>
#include <thread>
#include <evhttp.h>
struct event_base *eb;
std::thread t;
static volatile sig_atomic_t bailout = false;
void my_signal_handler(int) {
bailout = true;
}
void onRequest(evhttp_request *req, void *) {
struct evbuffer *OutBuf = evhttp_request_get_output_buffer(req);
evbuffer_add_printf(OutBuf, "<html><body>Testing 1-2-3</body></html>");
evhttp_send_reply(req, HTTP_OK, "OK", OutBuf);
}
void dispatch() {
eb = event_base_new();
struct evhttp *http = evhttp_new(eb);
evhttp_set_gencb(http, &onRequest, NULL);
evhttp_bind_socket_with_handle(http, "0.0.0.0", 5555);
event_base_dispatch(eb);
}
int main() {
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = my_signal_handler;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
t = std::thread { &dispatch };
while ( ! bailout ) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
event_base_loopexit(eb, NULL);
t.join();
}
行为是,如果您 运行 程序,请求页面,按 Ctrl-C 中止程序,event_base_dispatch() 保持 运行ning 直到 你获取另一个网页。只有这样循环才会中止并且程序终止。
如果您需要在 运行 任何更多回调之前退出事件循环,请使用 event_base_break()
http://www.wangafu.net/~nickm/libevent-book/Ref3_eventloop.html#_stopping_the_loop
最后我通过添加一个基本上轮询 bailout 变量的计时器来实现打破调度循环:
struct event *ev;
const struct timeval one_sec = { 1, 0 }; // sec, usec
void cb_timer_func(evutil_socket_t, short, void) {
if ( bailout ) {
event_base_loopbreak(eb);
}
else if ( ! evtimer_pending(ev, NULL) ) {
evtimer_del(ev);
evtimer_add(ev, &one_sec);
}
}
并且在调度循环中,我添加了:
ev = evtimer_new(eb, cb_timer_func);
evtimer_add(ev, &one_sec);
另一种方法是将 event_base_loopbreak()
放入信号处理程序。