ng_queue_t is a sequential container provided by Nginx, which organizes the data together in a doubly linked list.
The advantage of a linked list as a sequential container is that it efficiently performs insertions, deletions, merges, and so on, while moving the elements in the list only by modifying the pointer's direction, so it is well suited for frequently changing containers.
Compared to other sequential containers, it has the following three points:
(1) to achieve the sorting function, the amount is the insertion sort, although not very suitable for super-large-scale data sorting, but simple and practical.
(2) It is very lightweight and is not responsible for allocating the memory allocated by the list elements. ngx_queue_t just put these allocation number elements in a two-way chain.
(3) Support the merging of two linked lists.
Nginx in the design of this doubly linked list, because the container and elements share the ngx_queue_t structure, in order to avoid this structure members of the meaning of confusion, Nginx encapsulates the list of containers and elements of all methods.
ngx_queue_t header file:
typedef struct NGX_QUEUE_S ngx_queue_t;struct ngx_queue_s {ngx_queue_t *prev; ngx_queue_t *next;}; #define NGX_QUEUE_INIT (q) \ Initialize, empty, point to the container structure (q)->prev = q; \ (q)->next = Q#define Ngx_queue_empty (h) \ is empty (H = (h)->prev) #define Ngx_queue_insert_head (h, X) \ Insert List container Head (x)->next = (h)->next; \ (x)->next->prev = x; \ (x)->prev = h; \ (h)->next = X#define ngx_queue_insert_after ngx_queue_insert_head#define ngx_queue_insert_tail (h, X) \ Insert List container tail (x)->prev = (h)->prev; \ (x)->prev->next = x; \ (x)->next = h; \ (h)->prev = X#define ngx_queue_head (h) \ Returns the first struct pointer (h) Next#define ngx_queue_last (h) \ Returns the last struct pointer (h)->prev#define ngx_ Queue_sentinel (h) \ Returns the container struct pointer (h) #define NGX_QUEUE_NEXT (q) \ Returns the next element of Q (q)->next#define Ngx_queue_prev (q) \ Returns the previous element of Q (q)->prev#if (ngx_debug) #define NGX_QUEUE_REMOVE (x) \ (x)->next->prev = (x)->prev; \ (x)->prev->next = (x)->next; \ (x)->prev = NULL; \ (x)->next = Null#else#define ngx_queue_remove (x) \ Delete x (x)->next->prev = (x)->prev; \ (x)->prev->next = (x)->next#endif#define ngx_queue_split (H, q, N) \ split into two linked list (n)->prev = (h)->prev; \ (n)->prev->next = n; \ (n)->next = q; \ (h)->prev = (q)->prev; \ (h)->prev->next = h; \ (q)->prev = n; #define NGX_QUEUE_ADD (h, N) \ Merge list (h)->prev- >next = (n)->next; \ (n)->next->prev = (h)->prev; \ (h)->prev = (n)->prev; \ (h)->prev->next = h; #define NGX_QUEUE_DATA (q, type, link) \ Returns the address of the struct to which Q belongs (Type *) ((U_char *) q-offsetof (type, link))
N There are only two methods in the gx_queue_t implementation file: One is to return the central element in the linked list, and the other is to sort the list.
ngx_queue_t *ngx_queue_middle (ngx_queue_t *queue)//Return list center element {ngx_queue_t *middle, *next; Middle = ngx_queue_head (queue); if (middle = = Ngx_queue_last (queue)) {//special case should also be judged separately, if there is only one, then return this element to middle; } next = Ngx_queue_head (queue); for (;;) {middle = ngx_queue_next (middle); One pointer goes one step, the other pointer goes two steps next = Ngx_queue_next (next); if (next = = Ngx_queue_last (queue)) {//next Each step must judge the return middle; } next = Ngx_queue_next (next); if (next = = Ngx_queue_last (queue)) {//This also must be judged, consider really comprehensive AH return middle; }}}/* The stable insertion sort */voidngx_queue_sort (ngx_queue_t *queue, ngx_int_t (*cmp) (const ngx_queue_t *, cons T ngx_queue_t *))//With Insert method {ngx_queue_t *q, *prev, *next; Q = ngx_queue_head (queue); if (q = = Ngx_queue_last (queue)) {//Only one node is not queued for return; } for (q = ngx_queue_next (q); Q! = Ngx_queue_sentinel (queue); Q = next) {prev = Ngx_queue_prev (q); Save the front and back nodes of q separately next = Ngx_queue_next (q); Ngx_queue_remove (q); Do {if (CMP (prev, q) <= 0) {//If Prev is less than, this loop ends break; } prev = Ngx_queue_prev (prev);//otherwise than the previous element (prev! = Ngx_queue_sentinel (queue));//This is the end condition, prev is the linked list struct End Ngx_queue_insert_after (prev, q);//Insert Q}}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
The above describes the Nginx high-level data structure source analysis (a)-----Two-way list, including the aspects of the content, I hope that the PHP tutorial interested in a friend helpful.