在前面我们对整个libevent重要的核心(event
和event_base
)结构做了分析, 处于茫然你现在跟着再来看一下event
的初始化过程, 以及事件的注册/注销过程.
event的成员有很多, 所以我们需要对event
初始化操作做一个简单的封装才行, 不然用户怎么可能不会记错记混这些参数呢.
event
初始化函数是 event_set
.
void event_set(struct event *ev, int fd, short events,void (*callback)(int, short, void *), void *arg);
长长的一串…这下event函数的参数又要会过去看event
结构才行(经常要回过去看event
和event_base
结构)
参数
event
结构函数能看到要出初始化的成员很少, 其他的优先级等成员就是默认设置, 现在我们来看一个源码.
源码位置 event.c
// 设置event 结构, 初始化
// fd : 文件描述符
// events : 设置监听事件
// callback : 设置回调函数.
// arg : 设置回调函数的第三个参数
void
event_set(struct event *ev, int fd, short events,
void (*callback)(int, short, void *), void *arg)
{
/* Take the current base - caller needs to set the real base later */
// 通过默认设置的 current_base 初始化
ev->ev_base = current_base;
ev->ev_callback = callback;
ev->ev_arg = arg;
ev->ev_fd = fd; // 设置文件描述符或者是信号编号
ev->ev_events = events;
ev->ev_res = 0;
ev->ev_flags = EVLIST_INIT; // 状态 : 已被初始化
ev->ev_ncalls = 0; // 调用次数为0
ev->ev_pncalls = NULL;
min_heap_elem_init(ev);
/* by default, we put new events into the middle priority */
// 设置初始优先级
if(current_base)
ev->ev_pri = current_base->nactivequeues/2;
}
看到了吗, 整个event_set
函数就是将成员变量进行初始, 大部分都是我们函数传入的参数, 其他没有被传入的参数就是默认设置的值. 比如 : ev_flags
默认设置就是EVLIST_INIT
表示ev被初始化过.
函数有有三个部分需要分析一下 :
min_heap_elem_init(ev) : 其实默认设置成 -1. 表示没有设置计时器.
void min_heap_elem_init(struct event* e) { e->min_heap_idx = -1; }
current_base : 这个变量我们没有讲过, 而且它是凭空出现的. 其实current_base
是libevent定义的一个event_base
全局变量. 这个我们待会来分析.
ev->ev_pri : 默认设置的为全局变量优先级个数的一半.
可以发现大部分成员都被默认初始化了, 但是如果想要重新初始化event_base
参数或者其他参数不想默认初始化的怎么办. 没关系, libevent也有其他函数初始化个被成员的.
// 重新设置 ev 中的event_base成员
int
event_base_set(struct event_base *base, struct event *ev)
{
/* Only innocent events may be assigned to a different base */
// 如果ev没有被初始化, 则出错
if (ev->ev_flags != EVLIST_INIT)
return (-1);
ev->ev_base = base;
ev->ev_pri = base->nactivequeues/2;
return (0);
}
event_base_set需要注意ev
必须被初始化过才能重新设置.
// 重新设置 ev 优先级
int
event_priority_set(struct event *ev, int pri)
{
// 如果当前事件已经处于激活状态了,则无法改变优先级了
if (ev->ev_flags & EVLIST_ACTIVE)
return (-1);
// 如果传入的pri的大小不符合则退出
if (pri < 0 || pri >= ev->ev_base->nactivequeues)
return (-1);
//设置优先级
ev->ev_pri = pri;
return (0);
}
event_priority_set 注意ev
如果已经就绪了就不能再设置优先级而且设置的优先级必须合理才行.
libevent定义的一个全局变量struct event_base current_base = NULL
. 由函数event_init
初始化.
struct event_base *
event_init(void)
{
struct event_base *base = event_base_new();
if (base != NULL)
current_base = base;
return (base);
}
而 event_init
主要调用的是event_base_new
函数. 现在是初始化明白就行了, 因为event_base_new
等到我们之后分析信号之后再来讲比较好.
原计划是还要分析完注册和注销, 但是看来篇幅还是不够, 我们下节来分析吧.
current_base
.