int event_base_priority_init(struct event_base *base, int n_priorities);以及
int event_priority_set(struct event *event, int priority);
阅读相关文档后得知, 第一个函数用于设置整个event_base的最大优先级数值
第二个函数则针对某个event设置其优先级.(优先级的值越大, 优先级越低; 值越小, 优先级越高)在event_new ---> event_assign 中, 有这么一句话:
ev->ev_pri = base->nactivequeues / 2;可见, 一般事件的初始化后优先级都是被设置为最大优先级数值的一半的
struct event_base { ... ... /** Set if we should terminate the loop once we're done processing * events. */ //设置了这个标志表示我们会中断当前的循环(但是会把当前正在执行的事件处理程序处理完) int event_gotterm; /** Set if we should terminate the loop immediately */ //结束当前的循环 int event_break; /** Set if we should start a new instance of the loop immediately. */ //终止当前的循环,重新从头开始这个循环 (就跟continue含义类似) int event_continue; /** The currently running priority of events */ //当前正在执行的事件的优先级 int event_running_priority; /* Active event management. */ /** An array of nactivequeues queues for active events (ones that * have triggered, and whose callbacks need to be called). Low * priority numbers are more important, and stall higher ones. */ //可以看出, 这里激活队列并不是只有一个,而是存在了一个激活队列的数组 //根据优先级的不同划分,优先级多大, 数组就多大 struct event_list *activequeues; /** The length of the activequeues array */ //这个其实就等于最大优先级数值 int nactivequeues; ... ... /** List of defered_cb that are active. We run these after the active * events. */ //被延迟的已激活的回调函数 struct deferred_cb_queue defer_queue; ... ... };
单纯的看这些结构体中的成员并没有什么太大的意义, 我们就地分析event_base_priority_init的代码:
int event_base_priority_init(struct event_base *base, int npriorities) { int i; /* #define N_ACTIVE_CALLBACKS(base) \ ((base)->event_count_active + (base)->defer_queue.active_count) 可以看出,这个宏是用于计算当前base已激活的event的总数加上被延迟的已激活的事件的总数的总合 也就是说,只要有事件已经被激活了或者可以假设说base已经开始运作了,再执行此函数是非法的!因此要求尽量在base开始之前就初始化这个最大优先级数值 */ 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; } //以上为初始化, 以下为根据提供的npriorities作出处理 /* Allocate our priority queues */ 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的优先级, 现在看看设置每个事件的优先级
int event_priority_set(struct event *ev, int pri) { _event_debug_assert_is_setup(ev); //不能对已经被激活的事件设置优先级, 这也在情理之中. 这也要求我们在开启event_base循环之前如果需要就要事先设置事件优先级, 否则一旦开始,事件随时可能变为激活状态 if (ev->ev_flags & EVLIST_ACTIVE) return (-1); if (pri < 0 || pri >= ev->ev_base->nactivequeues) return (-1); ev->ev_pri = pri; return (0); }
最后, 我们也知道了, 每个事件都有其优先级存在, 在事件被激活后也会根据其优先级插入到优先级队列中去
既然在源代码中我们看到每个优先级队列是由TAILQ实现的, 那么其插入方式也就很简单的使用对应的插入方式了