ngx_array.h
/*
* Copyright (C) Igor Sysoev
* Copyright (C) Nginx, Inc.
*/
#ifndef _NGX_ARRAY_H_INCLUDED_
#define _NGX_ARRAY_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
struct ngx_array_s {
void *elts; // 指向数组始地址
ngx_uint_t nelts; // 数组里已经存储了几个元素
size_t size; // 数组中每个元素的大小
ngx_uint_t nalloc; // 数组总共可以储存多少个元素
ngx_pool_t *pool; // 数组的内存是由哪个pool分配的
};
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);
/*
数组初始化函数
@param array 储存数组元数据的结构体指针
@param pool 用于分配内存的pool
@param n 该数组分配共可以存储几个元素
@param size 该数组中每个元素的大小
@return NGX_OK | NGX_ERROR
*/
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;
// 数组可以储存n个size大小的元素
array->nalloc = n;
array->pool = pool;
// 给数组分配n*size大小的内存
array->elts = ngx_palloc(pool, n * size);
if (array->elts == NULL) {
return NGX_ERROR;
}
return NGX_OK;
}
#endif /* _NGX_ARRAY_H_INCLUDED_ */
ngx_array.c
/*
* Copyright (C) Igor Sysoev
* Copyright (C) Nginx, Inc.
*/
#include <ngx_config.h>
#include <ngx_core.h>
/*
创建数组函数
@param pool 用于分配内存的pool
@param n 该数组分配共可以存储几个元素
@param size 该数组中每个元素的大小
@return 存储数组元数据的ngx_array_t结构体
*/
ngx_array_t * ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size)
{
ngx_array_t *a;
// 在pool里给存储元数据的结构体分配内存
a = ngx_palloc(p, sizeof(ngx_array_t));
if (a == NULL) {
return NULL;
}
// 在pool里给数组分配内存,并用a->elts指向始地址
a->elts = ngx_palloc(p, n * size);
if (a->elts == NULL) {
return NULL;
}
// 初始化结构体的成员
a->nelts = 0;
a->size = size;
a->nalloc = n;
a->pool = p;
return a;
}
/*
销毁数组函数 这个函数在nginx中并没有用到
@param a 储存数组元数据的结构体指针
*/
void ngx_array_destroy(ngx_array_t *a)
{
ngx_pool_t *p;
p = a->pool;
// 判断是否p->last指针的值是否恰好等于数组的末地址,否则会”释放“数组和p->last之间的数据
if ((u_char *) a->elts + a->size * a->nalloc == p->d.last) {
p->d.last -= a->size * a->nalloc;
}
if ((u_char *) a + sizeof(ngx_array_t) == p->d.last) {
p->d.last = (u_char *) a;
}
}
/*
在原数组基础增加一个元素空间,如果原数组空间不够需要重新开辟内存
@param a 储存数组元数据的结构体指针
@return elt 新增内存的首地址
*/
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;
// 如果数组的末地址和p->last指针相等并且追加size大小的空间后不会超过p->end,才能追加分配内存
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大小的内存,并且nalloc+1表示数组可以数组可以储存的元素个数加1
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;
}
}
/*
数组原来就有空间,或者数组已经存满并且追加内存分配成功,或者数组存满并重新开辟了内存,
a->elts + a->size * a->nelts都等于此时数组的第一个可用地址,也就是下一个数据可以由
这个地址开始存储,elt只需要指向此时的数组末地址就行,
*/
elt = (u_char *) a->elts + a->size * a->nelts;
// 数组已存储的元素个数加一
a->nelts++;
// 返回数组第一个可用的内存地址,也就是下一个数据可以由这个地址开始存储
return elt;
}
/*
在原数组基础增加n个元素空间,如果原数组空间不够需要重新开辟内存
@param a 储存数组元数据的结构体指针
@return elt 新增内存的首地址
*/
void * ngx_array_push_n(ngx_array_t *a, ngx_uint_t n)
{
void *elt, *new;
size_t size;
ngx_uint_t nalloc;
ngx_pool_t *p;
size = n * a->size;
// 数组增加n个元素后超过可存储元素的个数
if (a->nelts + n > a->nalloc) {
/* the array is full */
p = a->pool;
// 同ngx_array_push函数
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
*/
p->d.last += size;
a->nalloc += n;
} else {
/* allocate a new array */
/*
如果追加的元素个数n比原来可存储的元素个数a->nalloc还大,否则开辟2*a->nalloc个空间可能还是比n小,
例如之前最大能存储5个,已经存储了2个,现在需要多存储12个,那么5*2<12,
,所以需要重新开辟2*n个空间,保证能多存储n个元素,其他的同ngx_array_push函数。
*/
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;
}