nginx数据结构ngx_queue_t

本文详细介绍了Nginx中ngx_queue_t数据结构的实现原理与使用方法,并通过一个具体案例展示了如何利用该数据结构实现双向队列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.概述
nginx为了跨平台底层封装了自己的数据结构,今天学了ngx_queue_t这个数据结构,这个结构实现了双向队列,该双向队列可以应用到任意结构体中把相应的结构体按照队列的方式组织起来.

2.代码


/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */


#include <ngx_config.h>
#include <ngx_core.h>


#ifndef _NGX_QUEUE_H_INCLUDED_
#define _NGX_QUEUE_H_INCLUDED_


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)->next


#define ngx_queue_prev(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)->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)                                         \
    (type *) ((u_char *) q - offsetof(type, link))


ngx_queue_t *ngx_queue_middle(ngx_queue_t *queue);
void ngx_queue_sort(ngx_queue_t *queue,
    ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *));


#endif /* _NGX_QUEUE_H_INCLUDED_ */

ngx_queue_data宏才是这个数据结构能够用到任何地方的关键,该宏通过指向ngx_queue_t的指针来算出自己的节点的指针.从而提供访问节点中其他数据的能力.

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


/* 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);
        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);
    }
}

3 一个小的case来使用上面定义的数据结构

#include "ngxqueue.h"
#include <stdio.h>
#include <stdlib.h>
typedef struct MyNode{
        int x;
        double y;
        ngx_queue_t ngx_queue;
} MyNode;
struct eventQueue{
    int count;
    int other;
    ngx_queue_t queue_sentinel;

};
struct eventQueue evqueue;

static int 
eventQueueInit(struct eventQueue *evqueue){
    evqueue->count = 0;
    evqueue->other = 0;
    ngx_queue_init(&evqueue->queue_sentinel);
    return 0;
}
static int 
eventQueueAdd(struct eventQueue* evqueue,struct MyNode* node){
    ngx_queue_insert_tail(&evqueue->queue_sentinel,&node->ngx_queue);
    evqueue->count++;
}
static void
printtheQ(struct eventQueue* evqueue){
    ngx_queue_t *p =ngx_queue_head(&evqueue->queue_sentinel);
    while( p != &evqueue->queue_sentinel){
        struct MyNode* tmp = ngx_queue_data(p,struct MyNode,ngx_queue);
        printf("the value is %d\n",tmp->x);
        p = ngx_queue_next(p);
    }

}
#define QNUM 5
int main(){
    eventQueueInit(&evqueue);
    int i;
    for(i =0 ; i < QNUM ;i++){
        struct MyNode* p = (struct MyNode*) malloc(sizeof(struct MyNode));
        p->x = i;
        p->y = i;
        eventQueueAdd(&evqueue,p);
    }
    printtheQ(&evqueue);

}

节点MyNode 将ngx_queue_t作为成员提供连接的能力, ngx_queue_t的哨兵节点作为eventQueue的成员, eventQueue可以负责管理整个队列,比如说count 负责记录整个队列的元素个数, 就可以基于ngx_queue_t 提供的操作来封装eventQueue自己的接口了.
比如在printQueue函数中调用ngx_queue_data来读取队列中节点的信息.

4总结
在c语言中如此实现的数据结构提供了模板的能力, 数据结构不依赖于特定的类.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值