nginx自定义了双向循环队列数据结构, 顺带复习下这个经典的数据结构
<core/nginx_queque.h>
定义了基本的, 思想与linux内核定义的list相似, 都是在自定义结构体中包含ngx_queue_t指针, 利用其在结构体中的offset串起来.linux
struct ngx_queue_s { ngx_queue_t *prev; ngx_queue_t *next; }; // 双向链表 #define ngx_queue_data(q, type, link) (type *) ((u_char *) q - offsetof(type, link)) //获取队列中节点数据, q是队列中的节点,type队列类型,link是队列类型中ngx_queue_t的元素名 #define ngx_queue_init(q) (q)->prev=(q); (q)->next=(q) // 初始化链表 #define ngx_queue_empty(h) (h == (h)->prev) // 根据头结点判断链表是否为空, 空链表的prev和next指针都指向自身, 形态如图:#define ngx_queue_insert_head(h, x) \ (x) –>next = h->next; (x)->next->prev=(x); \ (x) –>prev = h; h->next = (x) // 插入链表头部
#define ngx_queue_insert_tail(h, x) \ (x)->prev=(h)->prev; (x)->prev->next = x; \ (x)->next=h; (h) –>prev = x // 插入链表尾部
#define ngx_queue_remove(x) (x)->next->prev=(x)->prev;(x)->prev->next=(x)->next // 双向链表中删除节点
#define ngx_queue_head(h) (h)->next #define ngx_queue_tail(h) (h)->prev // 找到链表头, 尾 #define ngx_queue_next(q) (q)->next #define ngx_queue_prev(q) (q)->prev // 向前,后遍历链表用
#define ngx_queue_split(h, q, n) \ (n)->prev = (h) >prev; (h)->prev->next = n; \ (n)->next = q; (h)->prev=(g)->prev; \ (h)->prev->next = h; (q)->prev=n // h为链表头, q为待分割节点, n为分割后新链表的头结点, n->next = q, 如图为6个步骤
#define ngx_queue_add(h, n) \ (h)->prev->next=(n)->next;(n)->next->prev=(h)->prev; \ (h)->prev=(n)->prev; (h)->prev->next=h; // 队列n链接到到队h的队尾, 4个步骤
<core/nginx_queue.c>nginx
ngx_queue_t * ngx_queue_middle(ngx_queue_t *queue)
返回队列的中间节点, 若是除head外偶数个节点, 返回后半部分第1个节点
算法
队列形态 | 返回节点 |
header | header |
header->A | A |
header->A->B | B |
header->A->B->C | B |
header->A->B->C->D | C |
实现算法是 2个指针middle每次走一格, next每次走2格, next走到队尾后middle指向队列中间节点 数据结构
void
ngx_queue_sort(ngx_queue_t *queue, ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *))
根据自定义cmp函数完成对queue的排序, 好比在nginx.conf配置进行location级别的配置项管理时会对location队列排序函数