原文地址:
http://zhyclt.blog.163.com/blog/static/839359200881210428951/ libevent是一个针对*nix的高级IO的库(FreeBSD:kqueue, Linux:epoll, Solaris:/dev/poll)的封装(虽然对于windows它也能工作,不过它封装的不是iocp,所以这里就不讨论了)。现在我们看看libevent的实现结构。
1、libevent使用的数据结构简介
libevent中使用了tail queue、red black tree,现在简单总结一下,免得我自己忘了。
1、tail queue:
它的基本特性和单向链表一样,但是在它的head中增加了一个指向末尾的指针,所以它能够直接在链表的尾部插入数据,但是它所付出的代价是:
它实现的代码量要比同算法的单向链表增加15%,而且运行效率上要增加约20%的开销。
现在先看一个例子(以下代码只为了说明tail queue的使用,不考虑错误);
TAILQ_HEAD(my_tq, entry) head;
//just for show
struct my_tq *my_head;
struct entry {
...
TAILQ_ENTRY(entry) entry_tq;
...
};
my_head = malloc(sizeof(my_tq));
TAILQ_INIT(my_head);
TAILQ_INSERT_HEAD(my_head, p1 = malloc(sizeof(struct entry)), entry_tq);
TAILQ_INSERT_TAIL(my_head, p2 = malloc(sizeof(struct entry)), entry_tq);
TAILQ_INSERT_AFTER(my_head, p2, malloc(sizeof(struct entry)), entry_tq);
while (my_head->tqh_first != NULL)
TAILQ_REMOVE(my_head, my_head->tqh_first, entry_tq);
tail queue的操作相关宏:
TAILQ_HEAD(HEADNAME, TYPE) head --->定义串连TYPE类型的结构,同时将这种"新"类型的tail queue结构命名为HEADNAME, 最后还定义了一个变量“head”。
TAILQ_INIT(&head) --->初始化tail queue的两个指针,对列的头指针和队列的尾指针
TAILQ_ENTRY (TYPE) --->这个宏使用在TYPE结构体的定义内部,它定义维护结构体对象在tail queue中的位置所需要的指针。
TAILQ_INSERT_HEAD/TAILQ_INSERT_TAIL/TAILQ_INSERT_AFTER/TAILQ_REMOVE,这些宏的作用比较明显,需要注意的是它们都需要传入head指针和TAILQ_ENTRY定义的标识符。
(我觉得宏最强的地方和最有问题的地方就是它不进行类型检查,最让代码阅读者头痛的就是条件编译^_^)。
2、reb black tree
red black tree(rbt) 是一种近似的二叉平衡树,它的特点如下:
1、根节点是黑色的
2、表示rbt节点结构的空指针都会指向一个空的节点(rchild, lchild, lparent),而且空节点是黑色的
3、红色节点的rchild/lchild/parent都是红色节点
4、从根节点到空节点的任一路径所包含的黑色节点数是相同的
rbt很重要的一个操作就是子树旋转,它是调整rbt结构的辅助操作。例如:右旋转:
| |
A