1、數據結構
struct ngx_queue_s{
ngx_queue_t *prev;
ngx_queue_t *next;
};
備註:nginx的隊列是由具有頭節點的雙向循環列表實現的,每個節點結構爲ngx_queue_t,sizeof(ngx_queue_t)=8,nginx的隊列結構裏並沒有其節點的數據內容。
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); //依次將節點插入到已經排好序的隊列鏈表中
}
}