Nginx:存储数组的链表

Posted 看,未来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nginx:存储数组的链表相关的知识,希望对你有一定的参考价值。

今天把昨天没铺开的几个数据结构全部铺开,明天上手高级数据结构。

我的困惑

这个链表我很喜欢,且这个构想在我的脑子里面存在很久了,但是一直没去实现。

它,是deque吗?deque,刚开始接触的时候有那么一丝欣喜,但是再进一步了解之后,嗯,大家不喜欢用是有原因的。

我一直没有去实现它,我不是一个喜欢一直拖着的人,没有去实现,肯定是有原因的。
这么一种数据结构,它存在的意义是什么呢?对于每一块内存,都要专门开辟一个位置来记录它的空间,说是插入效率会比较高,但是真的能比普通数组高到哪里去呢?说是查询效率比较高,又能比链表高到哪里去?

这些问题我一直没有想明白,所以就不冒冒失失去实现了。

今天我就来为这些问题,找到一个出路!


存储数组的链表

typedef struct ngx_list_part_s  ngx_list_part_t;

//节点
/*
每个链表元素ngx_list_part_t又是一个数组,拥有连续的内存,
它既依赖于ngx_list_t里的size和nalloc来表示数组的容量,
同时又依靠每个ngx_list_part_t成员中的nelts来表示数组当前已使用了多少容量。
*/
struct ngx_list_part_s {
    void             *elts;		//指向数组的起始地址
    ngx_uint_t        nelts;	//表示数组中已经使用元素数量
    ngx_list_part_t  *next;		//下一个链表元素的地址
};

//链表
typedef struct {
    ngx_list_part_t  *last;		//指向最后一个数组元素
    ngx_list_part_t   part;		//首元素
    size_t            size;		//限制每个数组元素占用空间大小,也就是用户要存储的一个数据所 占用的字节数必须小于或等于size。
    ngx_uint_t        nalloc;	//最多可存储数据数
    ngx_pool_t       *pool;		//管理内存分配的内存池对象
} ngx_list_t;

这个跟deque有点像的东西我想实现它很久了,没想到在这里看到了。

设计优点

1、通用链表
2、小块的内存使用链表访问效率是低下的,使用数组通过偏移量来直接访问内存则要高 效得多。


配备方法

在 ngx_list 类里面就给了这几个方法,也没有什么删查改,呃呃呃。真就给了这几个而已。

//用于创建新的链表
ngx_list_t *ngx_list_create(ngx_pool_t *pool, ngx_uint_t n, size_t size);	

//用于初始化一个已有的元素
static ngx_inline ngx_int_t
ngx_list_init(ngx_list_t *list, ngx_pool_t *pool, ngx_uint_t n, size_t size);

//添加元素
void *ngx_list_push(ngx_list_t *list);

ngx_list_create

ngx_list_t *ngx_list_create(ngx_pool_t *pool, ngx_uint_t n, size_t size)
{
    ngx_list_t  *list;

    list = ngx_palloc(pool, sizeof(ngx_list_t));
    if (list == NULL) {
        return NULL;
    }

    if (ngx_list_init(list, pool, n, size) != NGX_OK) {
        return NULL;
    }

    return list;
}

ngx_list_create返回新创建的链表地址,如果创建失败,则返回NULL空指针。ngx_list_create 被调用后至少会创建一个数组(不会创建空链表),其中包含n个大小为size字节的连续内存 块,也就是ngx_list_t结构中的part成员。


ngx_list_init

static ngx_inline ngx_int_t
ngx_list_init(ngx_list_t *list, ngx_pool_t *pool, ngx_uint_t n, size_t size)
{
    list->part.elts = ngx_palloc(pool, n * size);
    if (list->part.elts == NULL) {
        return NGX_ERROR;
    }

    list->part.nelts = 0;
    list->part.next = NULL;
    list->last = &list->part;
    list->size = size;
    list->nalloc = n;
    list->pool = pool;

    return NGX_OK;
}

void *ngx_list_push(ngx_list_t *l)
{
    void             *elt;
    ngx_list_part_t  *last;

    last = l->last;

    if (last->nelts == l->nalloc) {

        /* the last part is full, allocate a new list part */

        last = ngx_palloc(l->pool, sizeof(ngx_list_part_t));
        if (last == NULL) {
            return NULL;
        }

        last->elts = ngx_palloc(l->pool, l->nalloc * l->size);
        if (last->elts == NULL) {
            return NULL;
        }

        last->nelts = 0;
        last->next = NULL;

        l->last->next = last;
        l->last = last;
    }

    elt = (char *) last->elts + l->size * last->nelts;
    last->nelts++;

    return elt;
}

哎,权当记录吧,希望读到后面,能慢慢清晰这个链表在nginx中的应用吧,这篇,终究缺了个点睛之笔。
我全局搜索了源码,其实用到的地方也不多。。。

以上是关于Nginx:存储数组的链表的主要内容,如果未能解决你的问题,请参考以下文章

如何用数组实现一个紧凑的链表?

05 链表(下):如何轻松写出正确的链表代码?

C语言当中的链表重要吗?可以做啥?

JZ-016-合并两个排序的链表

一文讲透链表操作,看完你也能轻松写出正确的链表代码

一文讲透链表操作,看完你也能轻松写出正确的链表代码