Nginx模塊開發—隊列模型

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);  //依次將節點插入到已經排好序的隊列鏈表中

    }

}



發佈了28 篇原創文章 · 獲贊 9 · 訪問量 25萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章