libevent中的尾队列tailq分析

libevent中的tailq本质上, 就是一个双向链表, 而后记录下了头指针和尾指针, 便于顺序遍历和逆序遍历.spa

因为C语言中没有模板, 为了适应不一样的数据类型, tailq的操做, 都是使用的宏定义, 致使代码难以阅读.指针

为了方便分析, 本文对tailq相关的结构体进行了简化:code

struct tailq{
    struct element*  first;
    struct element** last;
};
struct element{
    struct element*  next; //next必须放在第一个位置
    struct element** prev;
    int x;//这里表示结构体中的其它成员
};

读者可能有如下一些疑问:element

1. last和prev为何要使用指针地址, 直接用struct element*不是更简洁明了吗?event

看下面这段代码:    ast

struct element** prev;
struct element* elem = malloc(sizeof(struct element));
prev = &elem->next;

根据C语言的规则模板

由于elem == &elem->nextclass

因此: prev == elem效率

即:  next的值elem指针, prev的值也是elem的指针, 只不过形式上是struct element**, 使用时, 能够直接强转为struct elemnt*来操做遍历

写了一个普通的双向链表, 与之对比, 得出的结论是, tailq使用指针地址方式, insert_tail的操做少了一条if语句判断, 效率上更优.

2. 数据存储的结构是怎样的, 根据代码表面上的意义, 能够画出这样一张图:

绿色表示整个element

蓝色表示字段

白色表示值

因为&next的值, 等于element指针, 因此上图能够演变成

这样, 就很清晰了, prev指向前一个元素, next指向后一个元素, first指向第一人元素, last指向最后一个元素

相关文章
相关标签/搜索