创建了event_base对象,并且注册了一些事件之后,我们就希望Libevent可以在某个或某些事件被激活的时候能够及时的通知我们。
1.运行事件循环
(1)event_base_loop()
一旦创建了event_base对象并注册了事件之后,就可以通过event_base_loop()开启事件循环:
1 2 3 4 5 |
#define EVLOOP_ONCE 0x01 #define EVLOOP_NONBLOCK 0x02 #define EVLOOP_NO_EXIT_ON_EMPTY 0x04 int event_base_loop(struct event_base *base, int flags); |
其中,参数base是一个event_base对象;参数flag,可以用来改变event_base_loop()的行为,其可选值如上所示。
并且,默认情况下,在结束了事件注册之后,才会开启事件循环,该循环会反复的检查已注册事件是否被激活,一旦发现某个事件被激活,就会运行相应的回调函数。
然而,通过flag参数设置一个或多个标志,可以改变event_base_loop()函数的行为:
EVLOOP_ONCE:设置该标志,循环将一直等待直到某些事件被激活,然后运行所有的被激活事件,最后返回;
EVLOOP_NONBLOCK:设置该标志,循环将不再等待某些事件被激活,而是检查是否有事件将要触发,若有,则运行相应的回调函数后返回;
EVLOOP_NO_EXIT_ON_EMPTY:默认情况下,在没有等待事件或没有激活事件之后,循环会退出。设置该标志位,可以改变这一行为。
event_base_loop()函数的一般处理流程如下(伪代码):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
while (any events are registered with the loop, or EVLOOP_NO_EXIT_ON_EMPTY was set) { if (EVLOOP_NONBLOCK was set, or any events are already active) If any registered events have triggered, mark them active. else Wait until at least one event has triggered, and mark it active. for (p = 0; p < n_priorities; ++p) { if (any event with priority of p is active) { Run all active events with priority of p. break; /* Do not run any events of a less important priority */ } } if (EVLOOP_ONCE was set or EVLOOP_NONBLOCK was set) break; } |
(2)event_base_dispatch()
1 2 3 4 5 |
头文件:<event2/event.h> 原型:int event_base_dispatch(struct event_base *base); 功能:开启事件循环 参数:base——event_base对象 返回值:成功,0;失败,-1 |
相比于event_base_loop(),使用event_base_dispatch()函数更加容易使用,该函数不需要指定flag标志位。因此,该函数会一直运行,直到没有更多的注册事件或者直到遇到event_base_loopbreak()或event_base_loopexit()函数退出为止。
2.停止事件循环
通过下面的两个函数,可以让一个循环在所有注册事件被删除之前停止:
1 2 3 |
int event_base_loopexit(struct event_base *base, const struct timeval *tv); int event_base_loopbreak(struct event_base *base); |
(1)event_base_loopexit()
1 2 3 4 5 |
头文件:< event2/event.h> 原型:int event_base_loopexit(struct event_base *base, const struct timeval *tv); 功能:在指定的时间之后,退出事件循环 参数:base——event_base对象;tv——指定时间 返回值:成功,0;失败,-1 |
需要注意的是:如果tv为NULL,则立刻终止循环。但是,如果此时正在处理某个事件的回调函数,则会等到其执行完之后再终止循环。
(2)event_base_loopbreak()
1 2 3 4 5 |
头文件:<event2/event.h> 原型:int event_base_loopbreak(struct event_base *base); 功能:立即终止event_base_loop()循环 参数:base——event_base对象 返回值:成功,0;失败,-1 |
需要注意的是:该函数不同于调用event_base_loop(base, NULL);,因为后者会等待正在运行的回调函数结束才终止,而前者不然。
3.再次检查事件
通常,Libevent的循环机制是:循环检查事件==》运行所有激活的事件==》接着再检查事件……但是,有时我们会在某个事件回调函数执行之后停止Libevent循环(如前所述)。若想让Libevent再次扫描检查事件,则需要调用下面这个函数:
1 2 3 4 5 |
头文件:<event2/event.h> 原型:int event_base_loopcontinue(struct event_base *base); 功能:告诉event_base_loop()重新扫描事件 参数:base——event_base对象 返回值:成功,0;失败,-1 |
4.其他
其他可能会用到的函数还有:
(1)获取时间
int event_base_gettimeofday_cached(struct event_base *base, struct timeval *tv_out);
获取当前时间,而不是使用系统调用gettimeofday()。
(2)更新时间
int event_base_update_cache_time(struct event_base *base);
参考:
http://www.wangafu.net/~nickm/libevent-book/Ref3_eventloop.html