nginx代碼分析-基本結構-queue

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指針都指向自身, 形態如圖: image #define ngx_queue_insert_head(h, x) \  (x) –>next = h->next; (x)->next->prev=(x); \ (x) –>prev = h; h->next = (x) // 插入鏈表頭部 image
#define ngx_queue_insert_tail(h, x) \  (x)->prev=(h)->prev; (x)->prev->next = x; \ (x)->next=h; (h) –>prev = x // 插入鏈表尾部 image
#define ngx_queue_remove(x) (x)->next->prev=(x)->prev;(x)->prev->next=(x)->next // 雙向鏈表中刪除節點 image
#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個步驟
image
#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個步驟
image

<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隊列排序
函數

相關文章
相關標籤/搜索