Home  >  Article  >  Backend Development  >  nginx advanced data structure source code analysis (1) ----- doubly linked list

nginx advanced data structure source code analysis (1) ----- doubly linked list

WBOY
WBOYOriginal
2016-07-30 13:31:47982browse

ng_queue_t is a sequential container provided by Nginx, which organizes data together in a doubly linked list.

The advantage of a linked list as a sequential container is that it can efficiently perform operations such as insertion, deletion, and merging. When moving elements in the linked list, you only need to modify the pointing of the pointer. Therefore, it is very suitable for frequently modifying the container. occasion.

Compared with other sequential containers, it has the following three advantages:

(1) It implements the sorting function and uses insertion sorting, although it is not suitable for sorting very large-scale data. But simple and practical.

(2) It is very lightweight and is not responsible for the allocation of memory occupied by linked list elements. ngx_queue_t just links these allocated memory elements with a doubly linked list

(3) Supports the merging of two linked lists.

When Nginx designed this doubly linked list, since the container and elements share the ngx_queue_t structure, in order to avoid confusion in the meaning of the members of this structure, Nginx encapsulates all methods of the linked list container and elements.

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)                                                     \初始化,为空,都指向容器结构体
    (q)->prev = q;                                                            \
    (q)->next = q


#define ngx_queue_empty(h)                                                    \是否为空
    (h == (h)->prev)


#define ngx_queue_insert_head(h, x)                                           \插入链表容器头部
    (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)                                           \插入链表容器尾部
    (x)->prev = (h)->prev;                                                    \
    (x)->prev->next = x;                                                      \
    (x)->next = h;                                                            \
    (h)->prev = x


#define ngx_queue_head(h)                                                     \返回第一个结构体指针
    (h)->next


#define ngx_queue_last(h)                                                     \返回最后一个结构体指针
    (h)->prev


#define ngx_queue_sentinel(h)                                                 \返回容器结构体指针
    (h)


#define ngx_queue_next(q)                                                     \返回q的下一个元素
    (q)->next


#define ngx_queue_prev(q)                                                     \返回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)                                                   \删除x
    (x)->next->prev = (x)->prev;                                              \
    (x)->prev->next = (x)->next

#endif


#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;


#define ngx_queue_add(h, n)                                                   \合并链表
    (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)                                         \返回q所属结构体地址
    (type *) ((u_char *) q - offsetof(type, link))

n There are only two methods in the implementation file of gx_queue_t: one is to return the The central element and one is to sort the linked list.

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)) {              //next每走一步都要判断一下的
            return middle;
        }

        next = ngx_queue_next(next);

        if (next == ngx_queue_last(queue)) {               //这也要判断,考虑真全面啊
            return middle;
        }
    }
}


/* the stable insertion sort */

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);  //分别保存q的前后节点
        next = ngx_queue_next(q);

        ngx_queue_remove(q);

        do {
            if (cmp(prev, q) <= 0) {  //若prev小于,这个循环结束
                break;
            }

            prev = ngx_queue_prev(prev);//否则跟前面一个元素比

        } while (prev != ngx_queue_sentinel(queue));//这个为结束条件,prev为链表结构体结束

        ngx_queue_insert_after(prev, q);//插入q
    }
}

Copyright Statement: This article is an original article by the blogger and may not be reproduced without the blogger's permission.

The above introduces nginx advanced data structure source code analysis (1) ----- doubly linked list, including aspects of the content. I hope it will be helpful to friends who are interested in PHP tutorials.

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Previous article:php -> => problemNext article:php -> => problem