一.數據結構數組
單向鏈表, 每一個鏈表數據節點實際是一個數組, 數組總長度一致, 數組元素大小一致.數據結構
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