ngx_queue_t does not allocate memory, it simply connects the allocated memory with a doubly linked list. Consuming less memory, although too suitable for super-large-scale data sorting, but wins in simple use. As a general-purpose bidirectional linked list provided by C language, its design idea is worthy of reference. You can think of it as a circular structure when you understand the design.
typedef struct NGX_QUEUE_S ngx_queue_t;
struct ngx_queue_s {ngx_queue_t* prev; Ngx_queue_t* next;};
It is confusing that the container uses the same structure as its elements.
Operation
#define NGX_QUEUE_INIT (q) \
(q)->prev = q; \
(q)->next = q
Initializes the container when one end of the container (Prev/next) contains no elements, pointing to the container itself.
#define NGX_QUEUE_EMPTY (h) \
(H = = (h)->prev)
Determines whether the container is empty if the container is equal to the container's prev, the container does not contain any elements
#define Ngx_queue_insert_head (h, x) \
(x)->next = (h)->next; \
(x)->next->prev = x; \
(x)->prev = h; \
(h)->next = X
Insert element x in container h header:
#define Ngx_queue_insert_tail (h, x) \
(x)->prev = (h)->prev; \
(x)->prev->next = x; \
(x)->next = h; \
(h)->prev = X
add element x at container h tail
void Ngx_queue_sort (ngx_queue_t *queue, ngx_int_t (*cmp) (const ngx_queue_t *, const ngx_queue_t *));
Sorting the containers, the collation CMP is for the programmer to implement.
#define Ngx_queue_head (h) \
(h)->next
#define NGX_QUEUE_LAST (h) \
(h)->prev
Gets the head and tail elements of the container, respectively. At first glance it seems strange to get the head why is (h)->next instead of (h)->prev? Read the bottom of the few on the understanding.
There is a ngx_queue_t container ngx_queue_t gather;
Use Ngx_queue_init to initialize Ngx_queue_init (&gather);
When the container is empty, the situation is:
The case of a container containing 1 elements://Insert X in H Head, Ngx_queue_insert_head
Original: H->prev = H;h->next = h;
Process: X->next = h; The value of H->next is Hh->prev = x; The value of X->next is Hx->prev = H;h->next = x;
Container contains 2 elements of the case://In the H head and then insert Y, ngx_queue_insert_head original: H->prev = X;x->prev = H;h->next = X;x->next = h;
#define Ngx_queue_insert_head (h, y) \
(y)->next = (h)->next; \
(y)->next->prev = y; \
(y)->prev = h; \
(h)->next = y
Process: Y->next = x; (h) The value of->next is Xx->prev = y; (y) The value of->next is Xy->prev = H;h->next = y;
Case with 3 elements in container://add element Z at H tail, ngx_queue_insert_tail original:
H->next = Y;y->next = X;x->next = h;
X->prev = Y;y->prev = H;h->prev = x;
#define Ngx_queue_insert_tail (h, z) \
(z)->prev = (h)->prev; \
(z)->prev->next = z; \
(z)->next = h; \
(h)->prev = Z
Process:
Z->prev = X;x->next = Z;z->next = H;h->prev = Z;
As you can see, the prev of the container always points to the last element of the container, and next always points to the first element of the container. As if the container is a ring, the tail and tail of each other bite.
Use: (Examples from "deep Understanding Nginx: module Development and Architecture Analysis")
Ngx_queue_t can be a member of another struct, and then the struct object is linked to the linked list through that member. ngx_queue_t member location is arbitrary.
The following example creates a container, then adds 5 elements, and finally sorts
struct testnode{char* str; ngx_queue_t qt; int num;};
Sort functions, sorted by NUM ngx_int_t cmp (const ngx_queue_t* A, const ngx_queue_t* b) {//by Ngx_queue_data get the address of the struct Testnode object Te stnode* anode = Ngx_queue_data (A, Testnode, QT); testnode* BNode = Ngx_queue_data (A, Testnode, QT); return anode->num > Bnode->num;}
Traverse list void Trav (ngx_queue_t* q) {ngx_queue_t* idx; for (idx = ngx_queue_head (q); IDX! = Ngx_quque_sentinel (q); IDX = ngx_quque_next (idx)) {textnode* node = ngx_queue_data (idx, Testnode, QT); printf ("Num:%d\n", node->num); }}
Testnode Q; Testnode nodes[5];for (int i = 0; i < 5; ++i) Nodes[i].num = 5;
Ngx_queue_insert_tail (&q, &nodes[0].qt); Ngx_queue_insert_head (&q, &nodes[1].qt); Ngx_queue_insert _tail (&q, &nodes[2].qt); Ngx_queue_insert_head (&q, &nodes[3].qt); Ngx_queue_insert_tail (&q, &NODES[4].QT);
Traverse output Trav (&q);
Sort Ngx_queue_sort (&Q, CMP);
Traverse output Trav (&q);
NGINX Data Structure ngx_queue_t