Nginx模块开发—队列模型

来源:互联网 发布:让子弹飞 结局 知乎 编辑:程序博客网 时间:2024/06/06 06:55

1、数据结构

struct ngx_queue_s{       ngx_queue_t  *prev;    ngx_queue_t  *next;};

备注:nginx的队列是由具有头节点的双向循环列表实现的,每个节点结构为ngx_queue_tsizeof(ngx_queue_t)=8nginx的队列结构里并没有其节点的数据内容。

2、队列操作

ngx_queue_init(q)

函数功能:初始化队列。

#define ngx_queue_init(q)     (q)->prev = q;            (q)->next = q

ngx_queue_empty(h)

函数功能:判断队列是否为空。

#define ngx_queue_empty(h)       (h == (h)->prev)

ngx_queue_insert_head(h, x)

函数功能:在头节点之后插入新节点。

#define ngx_queue_insert_head(h, x)                             (x)->next = (h)->next;                                          (x)->next->prev = x;                                              (x)->prev = h;                                                 (h)->next = x


ngx_queue_insert_after

函数功能:在头节点之后插入新节点。

#define ngx_queue_insert_after   ngx_queue_insert_head

ngx_queue_insert_tail(h, x)

函数功能:在尾节点之后插入新节点。

#define ngx_queue_insert_tail(h, x)                      (x)->prev = (h)->prev;                              (x)->prev->next = x;                               (x)->next = h;                                     (h)->prev = x


ngx_queue_head

函数功能:取出第一个节点。

#define ngx_queue_head(h)              (h)->next

ngx_queue_last

函数功能:取出最后一个节点。

#define ngx_queue_last(h)                        (h)->prev

ngx_queue_next

函数功能:取出节点的后一个节点。

#define ngx_queue_next(q)                     (q)->next

ngx_queue_prev

函数功能:取出节点的前一个节点。

#define ngx_queue_prev(q)                               (q)->prev

ngx_queue_remove(x)

函数功能:删除节点。

#define ngx_queue_remove(x)                           (x)->next->prev = (x)->prev;                      (x)->prev->next = (x)->next;                     (x)->prev = NULL;                                (x)->next = NULL 


ngx_queue_split(h, q, n)

函数功能:分割队列。

#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_add(h, n)

函数功能:链接队列。

 #define ngx_queue_add(h, n)                             (h)->prev->next = (n)->next;                         (n)->next->prev = (h)->prev;                         (h)->prev = (n)->prev;                               (h)->prev->next = h; 

ngx_queue_data

#define ngx_queue_data(q, type, link)                   (type *) ((u_char *) q - offsetof(type, link))
备注:offsetof主要用于求结构体中一个成员在该结构体中的偏移量,第一个参数是结构体的名字,第二个参数是结构体成员的名字。

ngx_queue_t *ngx_queue_middle(ngx_queue_t *queue)

函数功能:获取队列的中间节点,若队列有奇数个节点(除头节点外),则返回中间的节点,若队列有偶数个节点,则返回后半个队列的第一个节点。

算法思想:middle指针每次后移一个节点,而next指针每次后移两个节点。
ngx_queue_t * ngx_queue_middle(ngx_queue_t *queue){    ngx_queue_t  *middle, *next;     middle = ngx_queue_head(queue);    if (middle == ngx_queue_last(queue)) {        return middle;    }     next = ngx_queue_head(queue);     for ( ;; ) {        middle = ngx_queue_next(middle);         next = ngx_queue_next(next);        if (next == ngx_queue_last(queue)) {   //奇数个节点            return middle;        }         next = ngx_queue_next(next);        if (next == ngx_queue_last(queue)) {   //偶数个节点            return middle;        }}} 

void ngx_queue_sort(ngx_queue_t *queue,ngx_int_t (*cmp)(const ngx_queue_t*, const ngx_queue_t*))

函数功能:排序队列,使用的是稳定的插入排序。

算法思想:从第一个节点开始遍历,依次将当前节点q插入到前面已经排好序的队列链表中。

Void ngx_queue_sort(ngx_queue_t *queue,    ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *)){    ngx_queue_t  *q, *prev, *next;     q = ngx_queue_head(queue);    if (q == ngx_queue_last(queue)) {        return;    }     for (q = ngx_queue_next(q); q != ngx_queue_sentinel(queue); q = next) {        prev = ngx_queue_prev(q);        next = ngx_queue_next(q);        ngx_queue_remove(q);         do {            if (cmp(prev, q) <= 0) {      //比较节点                break;            }            prev = ngx_queue_prev(prev);        } while (prev != ngx_queue_sentinel(queue));         ngx_queue_insert_after(prev, q);  //依次将节点插入到已经排好序的队列链表中    }}



原创粉丝点击