nginx_array
nginx内部自己实现了许多数据结构,这些数据结构是nginx项目的基石。
nginx_array是nginx实现的一个最基础的数据结构,其类型可以是根据自己的需要进行定义。
详见<nginx_array.h>中的:
typedef struct {
void *elts;
ngx_uint_t nelts;
size_t size;
ngx_uint_t nalloc;
ngx_pool_t *pool;
} ngx_array_t;
elts: 可以是ngx_keyval_t, ngx_str_t, ngx_bufs_t, ngx_hash_key_t等
nelts: 指出当前已使用的elts的个数
size: 每个elts的大小
nalloc: 指定申请被申请的空间能够容纳的元素个数
pool: 指向当前分配空间的内存池
nginx对外的函数:
ngx_array_t *ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size);
void ngx_array_destroy(ngx_array_t *a);
void *ngx_array_push(ngx_array_t *a);
void *ngx_array_push_n(ngx_array_t *a, ngx_uint_t n);
ngx_array_create以及ngx_array_destroy这两个函数比较简单,创建和内存回收的真正动作是由内存池相关动作所实现,因此销毁动作只是将指针指回之前未申请array的地址。
array_push和array_push_n在array的nelts剩余足够使用的,那么便直接使用,否则就要重新从内存池申请内存,而区别就在此:
ngx_array_push:
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
* 对于内存池所剩空间足够的,那么就直接扩容一个size
*/
p->d.last += a->size;
a->nalloc++;
} else {
/**
*allocate a new array
*如果当前内存池中剩余的空间小于本次需要新增的空间,
*那么对ngx_array_push方法来说,
*会将原先动态数组的容量扩容一倍
*/
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_n:
if (a->nelts + n > a->nalloc) {
/* the array is full */
p = a->pool;
if ((u_char *) a->elts + a->size * a->nalloc == p->d.last
&& p->d.last + size <= p->d.end)
{
/**
* the array allocation is the last in the pool
* and there is space for new allocation
*如果当前内存池中剩余的空间大于或者等于本次需要新增的空间,
*那么本次扩容将只扩充新增的空间。
*对于ngx_array_push_n来说,就是扩充n个元素。
*/
p->d.last += size;
a->nalloc += n;
} else {
/**
* allocate a new array
*如果当前内存池中剩余的空间小于本次需要新增的空间,
*对于ngx_array_push_n来说,
*如果参数n小于原先动态数组的容量,
*将会扩容一倍;如果参数n大于原先动态数组的容量,
*这时会分配2×n大小的空间。
*/
nalloc = 2 * ((n >= a->nalloc) ? n : a->nalloc);
new = ngx_palloc(p, nalloc * a->size);
if (new == NULL) {
return NULL;
}
ngx_memcpy(new, a->elts, a->nelts * a->size);
a->elts = new;
a->nalloc = nalloc;
}
}
elt = (u_char *) a->elts + a->size * a->nelts;
a->nelts += n;
return elt;
}