一.数据结构数组
单向链表, 每一个链表数据节点实际是一个数组, 数组总长度一致, 数组元素大小一致.数据结构
ngx_list_t为链表头节点, 定义了链表数据节点数组中数据元素大小(size), 每一个节点最大的数据个数(nalloc), 以及一个last指针指向链表的尾部数据节点方便插入数据操做.函数
ngx_list_part_t为链表数据节点, 记录了当前数组中已占用元素的个数, next指针指向下一节点.ui
struct ngx_list_part_s { void *elts; // 实际数据, n * size ngx_uint_t nelts; // 节点数组已经使用的元素个数 ngx_list_part_t *next; // 链表next指针 }; typedef struct { ngx_list_part_t *last; // 指向链表中尾节点 ngx_list_part_t part; // 链表头结点 size_t size; // 链表中节点数组的元素大小 ngx_uint_t nalloc;// 链表中节点数组的元素个数 ngx_pool_t *pool; } ngx_list_t;
二.链表的建立spa
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; } 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); // 为头结点分配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; }
如图为初始化后链表结构, 首先在内存池ngx_pool_t中分配链表头ngx_list_t的空间, 再经过ngx_list_init函数分配链表头数据节点的空间, 大小为nalloc * size..net
三.链表的使用指针
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; }
对于已创建的链表, ngx_list_push返回1个新元素的内存地址. 经过链表头的last指针找到链表尾节点, 若是elts中还有空间则分配一个元素, 不然新建一个链表数据节点ngx_list_part_t, 在新节点中分配,头结点指向该新节点code