【问题标题】:How to break out libevent's dispatch loop如何打破 libevent 的调度循环
【发布时间】:2015-03-23 20:02:42
【问题描述】:

我已经使用漂亮的 libevent 库在单独的线程中实现了一个小型网络服务器。网络服务器运行 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() 将继续运行直到您获取另一个网页。只有这样循环中止并且程序终止。

【问题讨论】:

    标签: c++ multithreading libevent


    【解决方案1】:

    如果您需要在运行更多回调之前退出事件循环,请使用 event_base_break()

    http://www.wangafu.net/~nickm/libevent-book/Ref3_eventloop.html#_stopping_the_loop

    【讨论】:

      【解决方案2】:

      最后,我通过添加一个基本上轮询 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);
      

      【讨论】:

        【解决方案3】:

        另一种方法是将event_base_loopbreak() 放入信号处理程序中。

        【讨论】:

          猜你喜欢
          • 2018-04-28
          • 2022-01-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-30
          • 2015-10-04
          • 2013-08-31
          相关资源
          最近更新 更多