Nginx链表设计

  • 单链表数据结构,初始化后自带一个头结点

  • 每一个链表节点存储一个动态数组,每次操作取一个数组元素内存

  • 不支持删除节点,只能添加(尾插法)

  • 使用内存池分配内存,只有当内存池释放时链表结构才能释放

    创建链表

  • 根据传入的数组大小 n和单个数组元素大小 size初始化链表结构

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

    链表初始化

  • 初始化 part结构体成员

  • last指针始终指向链表的最后一个节点

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

    image.png

取元素内存

  • 如果最后一个链表节点里面没有可分配的内存了,就新分配一个链表节点
  • 返回大小为 size的内存地址首地址
    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;
    }
    
    image _1_.png