nginx源码剖析数据结构篇(二) 双向链表ngx_queue_t
-
Author:Echo Chen(陈斌)
-
Email:chenb19870707@gmail.com
-
Date:October 20h, 2014
1.ngx_queue优势和特点
ngx_queue作为顺序容器链表,它优势在于其可以高效地执行插入、删除、合并操作,在插入删除的过程中,只需要修改指针指向,而不需要拷贝数据,因此,对于频繁修改的容器很适合。此外,相对于STL list,它还具有以下特点:
- 自身实现了排序功能
- 轻量级,不负责内存的分配
- 自身支持两个链表的合并
2.源代码位置
头文件:http://trac.nginx.org/nginx/browser/nginx/src/core/ngx_queue.h
源文件:http://trac.nginx.org/nginx/browser/nginx/src/core/ngx_queue.c
3.数据结构定义
1: typedef struct ngx_queue_s ngx_queue_t;
2:
3: struct ngx_queue_s {
4: ngx_queue_t *prev;
5: ngx_queue_t *next;
6: };
可以看到,它的结构非常简单,仅有两个成员:prev、next,这样对于链表中元素来说,空间上只增加了两个指针的消耗。
4.初始化ngx_queue_init
1: //q 为链表容器结构体ngx_queue_t的指针,将头尾指针指向自己
2: #define ngx_queue_init(q) \
3: (q)->prev = q; \
4: (q)->next = q
初始状态的链表如图所示:
5.判断链表容器是否为空ngx_queue_empty
判断方法非常简单,即判断链表的prev指针是否指向自己,如上图所示
1: #define ngx_queue_empty(h) \
2: (h == (h)->prev)
6.头部插入ngx_queue_insert_head
1: //h为链表指针,x为要插入的元素
2: #define ngx_queue_insert_head(h, x) \
3: (x)->next = (h)->next; \
4: (x)->next->prev = x; \
5: (x)->prev = h; \
6: (h)->next = x
标准的双链表插入四步操作,如图所示:
7.尾部插入ngx_queue_insert_tail
与头部插入类似,只是第一步给的h->prev ,即为最后一个结点:
1: #define ngx_queue_insert_tail(h, x) \
2: (x)->prev = (h)->prev; \
3: (x)->prev->next = x; \
4: (x)->next = h; \
5: (h)->prev = x
8.链表删除ngx_queue_remove
x为要删除的结点,将x的下一个的结点的prev指针指向x的上一个结点,再将x的前一个结点的next指针指向x的下一个结点,常规链表双链表结点删除操作,不处理内存释放
1: #define ngx_queue_remove(x) \
2: (x)->next->prev = (x)->prev; \
3: (x)->prev->next = (x)->next
4: