出处: http://blog.youkuaiyun.com/luotuo44/article/details/38512719
event_base允许用户对它里面的event设置优先级,这样可以使得有些更重要的event能够得到优先处理。
Libevent实现优先级功能的方法是:用一个激活队列数组来存放激活event。即数组的元素是一个激活队列,所以有多个激活队列。并且规定不同的队列有不同的优先级。
可以通过event_base_priority_init函数设置event_base的优先级个数,该函数实现如下:
-
- int
- event_base_priority_init(struct event_base *base, int npriorities)
- {
- int i;
-
-
-
- if (N_ACTIVE_CALLBACKS(base) || npriorities < 1
- || npriorities >= EVENT_MAX_PRIORITIES)
- return (-1);
-
-
- if (npriorities == base->nactivequeues)
- return (0);
-
-
-
- if (base->nactivequeues) {
- mm_free(base->activequeues);
- base->nactivequeues = 0;
- }
-
-
- base->activequeues = (struct event_list *)
- mm_calloc(npriorities, sizeof(struct event_list));
- if (base->activequeues == NULL) {
- event_warn("%s: calloc", __func__);
- return (-1);
- }
- base->nactivequeues = npriorities;
-
- for (i = 0; i < base->nactivequeues; ++i) {
- TAILQ_INIT(&base->activequeues[i]);
- }
-
- return (0);
- }
从前面一个判断可知,因为event_base_dispatch函数会改动激活事件的个数,即会使得N_ACTIVE_CALLBACKS(base)为真。所以event_base_priority_init函数要在event_base_dispatch函数之前调用。此外要设置的优先级个数,要小于EVENT_MAX_PRIORITIES。这个宏是在event.h文件中定义,在2.0.21版本中,该宏被定义成256。在调用event_base_new得到的event_base只有一个优先级,也就是所有event都是同级的。
上面的代码调用mm_alloc分配了一个优先级数组。不同优先级的event会被放到数组的不同位置上(下面可以看到这一点)。这样就可以区分不同event的优先级了。以后处理event时,就可以从高优先级到低优先级处理event。
上面是设置event_base的优先级个数。现在来看一下怎么设置event的优先级。可以通过event_priority_set函数设置,该函数如下:
-
- int
- event_priority_set(struct event *ev, int pri)
- {
- _event_debug_assert_is_setup(ev);
-
- if (ev->ev_flags & EVLIST_ACTIVE)
- return (-1);
-
-
- if (pri < 0 || pri >= ev->ev_base->nactivequeues)
- return (-1);
-
-
- ev->ev_pri = pri;
-
- return (0);
- }
在上面代码的第一个判断中,可以知道当event的状态是EVLIST_ACTIVE时,就不能对这个event进行优先级设置了。因此,如果要对event进行优先级设置,那么得在调用event_base_dispatch函数之前。因为一旦调用了event_base_dispatch,那么event就随时可能变成EVLIST_ACTIVE状态。
现在看一下一个event是怎么插入到event_base的优先级数组中。
-
-
- static void
- event_queue_insert(struct event_base *base, struct event *ev, int queue)
- {
- ....
-
- ev->ev_flags |= queue;
- switch (queue) {
- ...
- case EVLIST_ACTIVE:
- base->event_count_active++;
-
- TAILQ_INSERT_TAIL(&base->activequeues[ev->ev_pri],
- ev,ev_active_next);
- break;
- ...
- }
- }
最后,我们来看一下默认的event优先级是多少。想必大家都能想到这个默认优先级是在新建event结构体时设置的。不错,看下面的event_assign函数。
-
- int
- event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd,
- short events, void (*callback)(evutil_socket_t, short, void *), void *arg)
- {
- ...
-
- ev->ev_base = 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;
- ev->ev_pncalls = NULL;
-
- ....
-
- if (base != NULL) {
-
- ev->ev_pri = base->nactivequeues / 2;
- }
-
- ...
- }
在这个函数里面,对event的成员变量进行了一些设置。其中,优先级的设置值为优先级数组长度的一半,所以是中间优先级。