libevent 中的用户触发事件
Posted
技术标签:
【中文标题】libevent 中的用户触发事件【英文标题】:User triggered event in libevent 【发布时间】:2011-10-04 08:35:13 【问题描述】:我目前正在使用 libevent 编写一个多线程应用程序。
一些事件是由 IO 触发的,但我需要一些由代码本身跨线程触发的事件,使用 event_active()。
我试图编写一个简单的程序来显示我的问题所在:
事件是使用 event_new() 创建的,并且 fd 设置为 -1。
调用 event_add() 时,如果使用了 timeout 结构,该事件稍后会被 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 年超时作为解决方法。因此,如果这不是使用用户触发事件的正确方法,我想知道它是如何完成的。
【问题讨论】:
【参考方案1】:你的方法是正确的。在 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() 添加一个新标志,以防止它在循环没有事件时退出.补丁是over on Github;它主要是等待代码审查,并为选项取一个更好的名称。
【讨论】:
感谢尼克的快速回复。 我对此有一些意见: - 至于我目前的项目,我想我可以通过稍微不同地使用事件循环并使用超时来实际(不必要地)触发之后的处理来解决这个问题相对较长的等待(1 秒在服务器世界中是永恒的)。 - 为什么不让在 fd 或超时事件之上使用纯用户触发事件成为可能? - 如果事件将被忽略,event_add 不应该返回 0 以外的值吗?我被 event_base_add_virtual 技巧所吸引,但我更喜欢我的代码与更高版本兼容。 可以使用纯用户触发的事件:使用 event_new(base, -1/*no fd*/, 0/*no events*/, callback, callback_data) 创建它们。你用 event_active() 激活它们。但是,您不需要 event_add() 它们:event_add() 仅适用于基础应为自己轮询的事件。EVLOOP_NO_EXIT_ON_EMPTY
似乎是该标志的实际名称。
相关:***.com/questions/19757003/…【参考方案2】:
我刚刚被 libevent-2.0.21-stable 烧死了。这很明显是一个错误。我希望他们在未来的版本中修复它。同时,更新文档以警告我们会有所帮助。
最好的解决方法似乎是问题中描述的假超时。
@nickm,您没有阅读问题。他的示例代码使用 event_new() 就像你描述的那样; libevent 中存在一个错误,导致它在使用 NULL 超时时失败(但在调用 event_add() 时返回 0)。
【讨论】:
以上是关于libevent 中的用户触发事件的主要内容,如果未能解决你的问题,请参考以下文章