ngx_array_push
声明在 src\core\ngx_array.h
void *ngx_array_push(ngx_array_t *a);
实现在 src\core\ngx_array.c
void * ngx_array_push(ngx_array_t *a) { void *elt, *new; size_t size; ngx_pool_t *p; if (a->nelts == a->nalloc) { /* the array is full */ size = a->size * a->nalloc; p = a->pool; if ((u_char *) a->elts + size == p->d.last && p->d.last + a->size <= p->d.end) { /* * the array allocation is the last in the pool * and there is space for new allocation */ p->d.last += a->size; a->nalloc++; } else { /* allocate a new array */ new = ngx_palloc(p, 2 * size); if (new == NULL) { return NULL; } ngx_memcpy(new, a->elts, size); a->elts = new; a->nalloc *= 2; } } elt = (u_char *) a->elts + a->size * a->nelts; a->nelts++; return elt; }
ngx_array_push
函数的主要作用是向动态数组中添加一个新元素,并返回该元素的地址。如果数组已满,则会尝试扩展数组容量。
函数签名
void *ngx_array_push(ngx_array_t *a)
参数 :
a
是一个指向动态数组的指针。返回值 :
返回一个指向新元素的指针。如果内存分配失败,则返回
NULL
。
定义局部变量
void *elt, *new; size_t size; ngx_pool_t *p;
elt
:用于存储新元素的地址。
new
:用于存储新分配的数组地址(如果需要扩容)。
size
:当前数组占用的总内存大小。
p
:指向数组的内存池。这些变量将在后续代码中使用。
检查数组是否已满
if (a->nelts == a->nalloc) { /* the array is full */ ... }
如果
nelts
等于nalloc
,说明数组已满,无法直接添加新元素,需要进行扩容操作。
计算当前数组的总大小
size = a->size * a->nalloc;
size
表示当前数组占用的总内存大小,等于单个元素的大小乘以数组容量。
获取内存池指针
p = a->pool;
将数组的内存池指针赋值给局部变量
p
,方便后续操作。
检查是否可以直接扩展数组
if ((u_char *) a->elts + size == p->d.last && p->d.last + a->size <= p->d.end) { /* * the array allocation is the last in the pool * and there is space for new allocation */ p->d.last += a->size; a->nalloc++; }
这段代码检查两个条件:
当前数组是否是内存池中最后一个分配的内存块(
(u_char *) a->elts + size == p->d.last
),意味着当前数组占用的空间就在当前这个块中内存池的当前这个块是否有足够的剩余空间来扩展数组(
p->d.last + a->size <= p->d.end
)。如果满足这两个条件,说明可以直接在内存池中扩展数组:
将内存池的
last
指针向后移动a->size
字节。增加数组的容量(
a->nalloc++
)。这种方式避免了重新分配内存,提高了性能。
分配新的数组空间
else { /* allocate a new array */ new = ngx_palloc(p, 2 * size); if (new == NULL) { return NULL; } ngx_memcpy(new, a->elts, size); a->elts = new; a->nalloc *= 2; }
如果无法直接扩展数组,则需要分配一块新的内存:
调用
ngx_palloc
函数,从内存池中分配两倍于当前数组大小的内存(2 * size
)如果分配失败,返回
NULL
。使用
ngx_memcpy
将原数组的内容复制到新分配的内存中。更新数组的
elts
指针和容量(a->nalloc *= 2
)。这种方式通过加倍扩容策略,减少了频繁分配内存的开销。
计算并返回新元素的地址
elt = (u_char *) a->elts + a->size * a->nelts; a->nelts++; return elt;
计算新元素的地址:
(u_char *) a->elts + a->size * a->nelts
表示当前数组末尾的位置。增加数组的元素计数(
a->nelts++
)。返回新元素的地址。