Nginx--array数据结构解析

ngx_array_t是nginx内置的一个数据结构。
  1. 核心数据结构:
typedef struct {
    void        *elts;			//数组的第一个元素的地址
    ngx_uint_t   nelts;			//未使用的元素的索引
    size_t       size;			//数组中的每个元素的大小
    ngx_uint_t   nalloc;			//数组大小
    ngx_pool_t  *pool;			//数组依赖的内存池
} ngx_array_t;

  1. api概览:
//创建数组
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);

//两个push函数其实是从数组中申请一段数组内的内存,用于存储数据。和stl中的push有所区别,只执行了取地址,没有直接存储元素。



//构建数组
static ngx_inline ngx_int_t
ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size);
  1. 代码详解:
1. ngx_array_t *ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size);

		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)); //构建ngx_array_t结构
		    if (a == NULL) {
		        return NULL;
		    }
		
		    if (ngx_array_init(a, p, n, size) != NGX_OK) { //构建数组
		        return NULL;
		    }
		    return a;
		}

2. static ngx_inline ngx_int_t ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size);

		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;
		}
3. void *ngx_array_push(ngx_array_t *a);

		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)		/*内存池还有足够的空间保证至少能申请一个size大小的内存*/
		        {
		            /*
		             * the array allocation is the last in the pool
		             * and there is space for new allocation
		             */
		
					//扩展数组大小  +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;
		        }
		    }
		
		    elt = (u_char *) a->elts + a->size * a->nelts;
		    a->nelts++;
		
		    return elt;
		}
4. void *ngx_array_push_n(ngx_array_t *a, ngx_uint_t n)

//类似上一个函数,只是批量申请内存
		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;
		
		    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
		             */
		
		            p->d.last += size;
		            a->nalloc += n;
		
		        } else {
		            /* allocate a new array */
		
		            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;
		}


5. 数组销毁
//数组熊销毁的前提是数组所在的内存池在创建该数组后没有再创建其他数据结构。
		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;
		    }
		
		    if ((u_char *) a + sizeof(ngx_array_t) == p->d.last) {
		        p->d.last = (u_char *) a;
		    }
		}

//ps:ngx_array_t的创建和释放都依赖于nginx的内存池。

Reference:

[1] https://blog.csdn.net/initphp/article/details/50601742

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值