11

我目前正在使用 libevent 编写一个多线程应用程序。

一些事件是由 IO 触发的,但我需要几个由代码本身跨线程触发的事件,使用 event_active()。

我试图编写一个简单的程序来显示我的问题所在:

该事件是使用 event_new() 创建的,并且 fd 设置为 -1。

调用 event_add() 时,如果使用了超时结构,则该事件稍后会由 event_base_dispatch 正确处理。

如果改用 event_add(ev, NULL),它返回 0(显然成功),但 event_base_dispatch() 返回 1(这意味着没有事件没有正确注册。)

可以使用以下代码并交换 event_add 行来测试此行为:

#include <event2/event.h>
#include <unistd.h>

void cb_func (evutil_socket_t fd, short flags, void * _param) {
  puts("Callback function called!");
}

void run_base_with_ticks(struct event_base *base)
{
  struct timeval one_sec;

  one_sec.tv_sec = 1;
  one_sec.tv_usec = 0;
  struct event * ev1;
  ev1 = event_new(base, -1, EV_PERSIST, cb_func, NULL);
  //int result = event_add(ev1, NULL);
  int result = event_add(ev1, &one_sec);
  printf("event_add result: %d\n",result);

  while (1) {
     result = event_base_dispatch(base);
     if (result == 1) {
       printf("Failed: event considered as not pending dispite successful event_add\n");
       sleep(1);
     } else {
       puts("Tick");
     }
  }
}

int main () {
  struct event_base *base = event_base_new();
  run_base_with_ticks(base);
  return 0;
}

编译:g++ sample.cc -levent

问题是,我不需要超时,也不想使用 n 年超时作为解决方法。因此,如果这不是使用用户触发事件的正确方法,我想知道它是如何完成的。

4

2 回答 2

8

你的方法是合理的。在 Libevent 2.0 中,您可以使用 event_active() 从另一个线程激活事件。只需确保您事先适当地使用了 evthread_use_windows_threads() 或 evthread_use_pthreads() ,以告诉 Libevent 使用正确的线程库。

至于需要额外的事件:在 Libevent 2.0 及更早版本中,当没有添加未决事件时,事件循环将立即退出。您最好的选择可能是您发现的超时技巧。

如果你不喜欢这样,你可以使用内部的“event_base_add_virtual”函数告诉event_base它有一个虚拟事件。但是,此功能不会导出,因此您必须说:

    void event_base_add_virtual(struct event_base *);
    // ...
    base = event_base_new();
    event_base_add_virtual(base); // keep it from exiting

不过,这有点小技巧,而且它使用了一个未记录的函数,因此您需要注意以防它不能与更高版本的 Libevent 一起使用。

最后,这个方法现在对你没有帮助,但是对于 Libevent 的未来版本(2.1 和更高版本)有一个待处理的补丁来向 event_base_loop() 添加一个新标志,以防止它在循环没有事件时退出。补丁在 Github 上结束了;它主要是等待代码审查,并为选项取一个更好的名称。

于 2011-10-04T10:54:04.430 回答
1

我刚刚被 libevent-2.0.21-stable 烧死了。这很明显是一个错误。我希望他们在未来的版本中修复它。同时,更新文档以警告我们会有所帮助。

最好的解决方法似乎是问题中描述的假超时。

@nickm,您没有阅读问题。他的示例代码使用 event_new() 就像你描述的那样;libevent 中有一个错误,导致它在使用 NULL 超时时失败(但在调用 event_add() 时返回 0)。

于 2014-04-27T21:10:39.723 回答