nginx数组定义
typedef struct {
void *elts; //数组头指针
ngx_uint_t nelts; //当前使用的数组元素数量
size_t size; //数组元素大小
ngx_uint_t nalloc; //数组最大的元素个数
ngx_pool_t *pool; //内存池
} ngx_array_t;
数组的创建
static ngx_inline ngx_int_t ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size)
{
/*
* set "array->nelts" before "array->elts", otherwise MSVC thinks
* that "array->nelts" may be used without having been initialized
*/
array->nelts = 0;
array->size = size;
array->nalloc = n;
array->pool = pool;
array->elts = ngx_palloc(pool, n * size);
if (array->elts == NULL) {
return NGX_ERROR;
}
return NGX_OK;
}
ngx_array_t *ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size)
{
ngx_array_t *a;
//分配内存
a = ngx_palloc(p, sizeof(ngx_array_t));
if (a == NULL) {
return NULL;
}
//为ngx_array_t::elts分配内存,初始化nalloc,size,nelts
if (ngx_array_init(a, p, n, size) != NGX_OK) {
return NULL;
}
return a;
}
ngx_array_create很简单主要是分配ngx_array_t内存,并且初始化ngx_array_t的各个字段并为array->elts分配内存
数组的使用
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++;//最大元素个数+1
} else {
/* allocate a new array */
//重新分配2被的内存,拷贝之前的数据
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++;//使用元素+1
return elt;
}
- 如果数组没有使用完,直接返回地址并且使用元素+1
- 如果数组使用完
- 当前内存池的last指针指向数组内存末尾并且内存池有剩余的size大小的空间,则使用内存池分配一个内存
- 如果不满足,则重新分配比原来大两倍的内存并且拷贝之前的数据
- 返回地址需要在外面填充数据
还有一个函数ngx_array_push_n与这个函数的原理一样
数组的销毁
void ngx_array_destroy(ngx_array_t *a)
{
ngx_pool_t *p;
p = a->pool;
//当前内存池指向的地址刚好是数组的末尾
if ((u_char *) a->elts + a->size * a->nalloc == p->d.last) {
p->d.last -= a->size * a->nalloc;
}
//当前内存池指向的地址刚好是ngx_array_t的末尾
if ((u_char *) a + sizeof(ngx_array_t) == p->d.last) {
p->d.last = (u_char *) a;
}
}
nginx数组的销毁结合了内存池,数组本身并未做什么操作。
满足内存池last指针移动的连个条件
- 当前内存池指向的地址刚好是数组的末尾
- 当前内存池指向的地址刚好是ngx_array_t的末尾
注意只判断了p->d.last也就是第一个内存块,没有去遍历其他内存块