libevent的基本操作单元是事件,每个事件代表一组条件的集合,这些条件包括:
- 文件描述符已经就绪,可以读取或者写入
- 文件描述符变为就绪状态,可以读取或者写入(仅对于边沿触发IO)
- 超时事件
- 发生某信号
- 用户触发事件
所有事件具有相似的生命周期。调用libevent函数设置事件并且关联到event_base之后,事件进入"已初始化(initialized)"状态。此时可以将事件添加到event_base中,这使之进入"未决(pending)"状态。在未决状态下,如果触发事件的条件发生(比如说,文件描述符的状态改变,或者超时时间到达),则事件进入"激活(active)"状态,(用户提供的)事件回调函数将被执行。如果配置为"持久的(persistent)",事件将保持为未决状态。否则 ,执行完回调后,事件不再是未决的。删除操作可以让未决事件成为非未决(已初始化)的;添加操作可以让非未决事件再次成为未决的。
注意:事件进入激活状态的前提时,事件在未决状态下被触发。
1 构造事件对象
使用event_new()接口创建事件。
接口
#define EV_TIMEOUT 0x01
#define EV_READ 0x02
#define EV_WRITE 0x04
#define EV_SIGNAL 0x08
#define EV_PERSIST 0x10
#define EV_ET 0x20
typedef void ( * event_callback_fn)(evutil_socket_t, short, void* );
struct event* event_new(struct event_base * base, evutil_socket_t fd, short what, event_callback_fn cb,void* arg);
void event_free(struct event* event);
event_new()试图分配和构造一个用于base的新的事件:
- base:该事件关联的event_base;
- fd:文件描述符,event_base将会观察其特定类型事件;
- what:指定将会观察的特定类型事件;
- cb:事件被激活时,libevent将调用cb函数,入参为:fd,表示所有被触发事件的位字段,arg参数
- args:可扩展参数;
发生内部错误,或者传入无效参数时,event_new()将返 NULL。所有新创建的事件都处已初始化和非未决状态,调用event_add()可以使其成为未决的。要释放事件,调用event_free()。对未决或者激活状态的事件调用event_free()是安全的:在释放事件之前,函数将会使事件成为非激活和非未决的。
示例
#include <event2/event.h>
void cb_func(evutil_socket_t fd, short what, void* arg)
{
const char* data = arg;
printf("Got an event on socket %d:%s%s%s%s [%s]", (int) fd, (what&EV_TIMEOUT) ? "
timeout" : "", (what&EV_READ) ? " read" : "", (what&EV_WRITE) ? " write" : "",
(what&EV_SIGNAL) ? " signal" : "", data);
}
void main_loop(evutil_socket_t fd1, evuti