libevent源码学习2---事件循环event_loop

libevent源码学习2---事件循环event_loop

1.运行循环

一旦有了一个已经注册了某些事件的 event_base,就需要让 libevent 等待事件并且通知事件的发生。

c 复制代码
#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);

默认情况下,event_base_loop()函数运行 event_base 直到 其中没有已经注册的事件为止。执行循环的时候 ,函数重复地检查是否有任何已经注册的事件被触发 (比如说,读事件的文件描述符已经就绪,可以读取了;或者超时事件的超时时间即将到达 )。如果有事件被触发,函数标记被触发的事件为 "激活的",并且执行这些事件。

在 flags 参数中设置一个或者多个标志就可以改变 event_base_loop()的行为。

如果设置了 EVLOOP_ONCE ,循环将等待某些事件成为激活的 ,执行激活的事件直到没有更多的事件可以执行,然会返回。

如果设置了 EVLOOP_NONBLOCK,循环不会等待事件被触发, 循环将仅仅检测是否有事件已经就绪,可以立即触发,如果有,则执行事件的回调。

完成工作后,如果正常退出, event_base_loop()返回0;如果因为后端中的某些未处理错误而退出,则返回 -1。

为方便起见,也可以调用

c 复制代码
int event_base_dispatch(struct event_base *base);

event_base_dispatch()等同于没有设置标志的 event_base_loop()。所以,event_base_dispatch()将一直运行,直到没有已经注册的事件了,或者调用 了 event_base_loopbreak()或者 event_base_loopexit()为止。

2 停止循环

如果想在移除所有已注册的事件之前停止活动的事件循环,可以调用两个稍有不同的函数 。

c 复制代码
int event_base_loopexit(struct event_base *base, const struct timeval *tv);
int event_base_loopbreak(struct event_base *base);

event_base_loopexit()event_base 在给定时间之后停止循环。如果 tv 参数为 NULL, event_base 会立即停止循环,没有延时。

如果 event_base 当前正在执行任何激活事件的回调,则回调会继续运行, 直到运行完所有激活事件的回调之才退出。

event_base_loopbreak()event_base 立即退出循环。它与 event_base_loopexit (base, NULL)的不同在于, 如果 event_base 当前正在执行激活事件的回调 , 它将在执行完当前正在处理的事件后立即退出。

注意: event_base_loopexit(base,NULL)event_base_loopbreak(base) 在事件循环没有运行时的行为不同; 前者安排下一次事件循环在下一轮回调完成后立即停止(就好像带 EVLOOP_ONCE 标志调用一样); 后者却仅仅停止当前正在运行的循环, 如果事件循环没有运行, 则没有任何效果。

示例:

c 复制代码
void run_base_with_ticks(struct event_base *base)
{
    struct timeval ten_sec;
    ten_sec.tv_sec = 5;
    ten_sec.tv_usec = 0;

    event_base_loopexit(base, &ten_sec);
    event_base_dispatch(base);
    puts("Tick");
}
int main()
{
    event_base *base = event_init();
    run_base_with_ticks(base);
}

有时候需要知道对 event_base_dispatch()或者 event_base_loop()的调用是正常退出的, 还是因为调用 event_base_loopexit()或者 event_base_break()而退出的。可以调用下述函数来确定是否调用了 loopexit 或者 loopbreak函数。

c 复制代码
int event_base_got_exit(struct event_base *base);
int event_base_got_break(struct event_base *base);

这两个函数分别会在循环是因为调用 event_base_loopexit()或者 event_base_loopbreak()而退出的时候返回 true, 否则返回 false。下次启动事件循环的时候, 这些值会被重设。

为帮助调试程序(或者调试 libevent), 有时候可能需要加入到 event_base 的事件及其状态的完整列表。调用 event_base_dump_events()可以将这个列表输出到指定的文件中。

c 复制代码
void event_base_dump_events(struct event_base *base, FILE *f);

这个列表是人可读的, 未来版本的 libevent 将会改变其格式。

相关推荐
whowin11 天前
C程序员应该知道的最好的8个C编程框架
qt·libevent·gtk·libuv·glib·cmocka·ncurses
一眼万里*e4 个月前
libevent入门篇
c++·libevent
Philosophy5 个月前
libevent之evbuffer
libevent
dvlinker7 个月前
开源事件通知库libevent及网络连接管理模块bufferevent详解
libevent·回调·数据读写·开源事件通知库·网络连接管理·bufferevent·心跳处理
一只特立独行的猪( ﹡ˆoˆ﹡8 个月前
Libevent的使用及reactor模型
reactor·libevent
小胖西瓜9 个月前
如何在 libevent 中读取超过 4096 字节的数据
libevent
shanql1 年前
使用libevent实现回显服务器
libevent
OopspoO1 年前
libevent学习——event_base
c语言·学习·libevent
OopspoO1 年前
libevent数据结构——TAILQ_结构体
c语言·学习·libevent
Stack Overflow?Tan901 年前
libevent源码学习6---链接监听器evconnlistener
libevent