struct ngx_queue_s {
ngx_queue_t *prev;
ngx_queue_t *next;
};
注意nginx的队列操作和结构只进行指针的操作,不负责节点内容空间的分配和保存,所以在定义自己的队列节点的时候,需要自己定义数据结构以及分配空间,并包含一个ngx_queue_t类型的成员。
另外,整个queue结构中包含一个 sentinel(哨兵) 节点,他指向队列的头和尾,在nginx1.0.10中head就是sentinel
//初始化队列
ngx_queue_init(q)
//判断队列是否为空
ngx_queue_empty(h)
//在头节点之后插入新节点
ngx_queue_insert_head(h, x)
//在尾节点之后插入新节点
ngx_queue_insert_tail(h, x)
//删除节点x
ngx_queue_remove(x)
//分割队列
ngx_queue_split(h, q, n)
//链接队列
ngx_queue_add(h, n)
//获取队列的中间节点
ngx_queue_t *ngx_queue_middle(ngx_queue_t *queue)
//排序队列(稳定的插入排序)
void ngx_queue_sort(ngx_queue_t *queue,ngx_int_t (*cmp)(const ngx_queue_t*, const ngx_queue_t*))
分割队列
分割队列操作由宏ngx_queue_split完成,如下。
#define ngx_queue_split(h, q, n) \
(n)->prev = (h)->prev; \
(n)->prev->next = n; \
(n)->next = q; \
(h)->prev = (q)->prev; \
(h)->prev->next = h; \
(q)->prev = n;
该宏有3个参数,h为队列头(即链表头指针),将该队列从q节点将队列(链表)分割为两个队列(链表),q之后的节点组成的新队列的头节点为n,图形演示如下。
ngx_queue_t *ngx_queue_middle(ngx_queue_t *queue)查找中间节点,采用的是一个节点走两步,一个节点走一步的方法,同时需要作奇数和偶数的处理。演示图形如下。
void ngx_queue_sort(ngx_queue_t *queue,ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *))
采用的是插入排序的方式,cmp比较函数有点面向对象的意思。保证队列的有序。
看了这么多,抄了这么多,现在我还是没有队列的数据怎么存储的
获取队列的数据采用
ngx_queue_data(q, type, link) (type *) ((u_char *) q - offsetof(type, link))
由该宏定义可以看出,一般定义队列节点结构(该结构类型为type)时,需要将真正的数据放在前面,而ngx_queue_t结构放在后面,故该宏使用减法计算整个节点结构的起始地址(需要进行类型转换)。
例子:
} my_point_queue_t;
my_point_queue_t *point = ngx_queue_data(q, my_point_queue_t, queue);
参考文章 http://www.abo321.org/archives/218