Nginx的list单向链表的结构和Nginx的数组结构Array有点类似,总体来说,数据结构也是非常简单清晰的。
Nginx的单向链表也是固定了每个元素的大小,并且用单向链表的方式连接。
typedef struct ngx_list_part_s ngx_list_part_t; /** * 链表节点 每个节点大小 = size * 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; /* 这个链表默认的每个元素大小 */ ngx_uint_t nalloc; /* 每个节点part 可以支持多少个元素*/ ngx_pool_t *pool; /* 线程池*/ } ngx_list_t;
通过调用ngx_list_create创建一个list,并且可以指定每个元素的大小以及每个节点元素个数。
/** * 创建链表 */ ngx_list_t * ngx_list_create(ngx_pool_t *pool, ngx_uint_t n, size_t size) { ngx_list_t *list; /* 从内存池上面分配一块内存,存储ngx_list_t数据结构 */ list = ngx_palloc(pool, sizeof(ngx_list_t)); if (list == NULL) { return NULL; } /* 分配一个链表节点的内存块。内存大小 n * size*/ list->part.elts = ngx_palloc(pool, n * size); if (list->part.elts == NULL) { return NULL; } list->part.nelts = 0; /* 使用的元素个数 */ list->part.next = NULL; /* 下一个节点 */ list->last = &list->part; /* 最后一个节点地址 */ list->size = size; /* 每个元素的大小 */ list->nalloc = n; /* 分配多少个 */ list->pool = pool; /* 线程池 */ return list; }
使用ngx_list_push方法可以使用一个元素,并且返回元素的指针地址。如果节点元素已经用完,则会创建一个新的链表
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 */ /* 分配一块内存,存储ngx_list_part_t数据结构 */ last = ngx_palloc(l->pool, sizeof(ngx_list_part_t)); if (last == NULL) { return NULL; } /* 分配一个链表节点的内存块。内存大小 n * size*/ 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; }