`
wsql
  • 浏览: 11777795 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

nginx 源码学习笔记(八)——基本容器——array数组

 
阅读更多

对应文件为core/ngx_array.{c|h}

ngx_array是nginx内部封装的,使用ngx_pool_t对内存池进行分配的数组容器,其中的数据是在一整片内存区中连续存放的。更新数据时只能在尾部压入1个或多个元素。这里单纯的觉得和数组没有差别。

数组的实现结构为:

struct ngx_array_s {
    void        *elts;   //具体的数据区域的指针
    ngx_uint_t   nelts;   //数组实际包含的元素数量
    size_t       size;    //数组单个元素的大小
    ngx_uint_t   nalloc;   //数组容器预先(或者重新)分配的内存大小 !!!这部分为预计的存储元素数量!!!
    ngx_pool_t  *pool;    //分配的内存池
};

常用操作有:

//创建数组
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;
    }
    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;
}

//摧毁数组
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追后地址
        p->d.last -= a->size * a->nalloc;     //如果等于,指针迁移总数据量位数即可
    }
    if ((u_char *) a + sizeof(ngx_array_t) == p->d.last) {     //如果没有数据
        p->d.last = (u_char *) a;                       //直接把指针移动到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          //如果总数据量等于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;                    //last后移
            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;                       //可容纳总数量*2
        }
    }
    elt = (u_char *) a->elts + a->size * a->nelts;        //新指针用于返回
    a->nelts++;                                  //实际数量增加
    return elt;                                  //返回指针指向的地址,这里只进行内存分配,还需要对返回的新指针进行赋值,等操作才可以实现数组的添加,这里要特殊注意
}
//void * ngx_array_push_n(ngx_array_t *a, ngx_uint_t n) //对于这个函数就不多讲了



总结:

ngx_array_create 在未创建ngx_array_t结构体时创建数组
ngx_array_init 在创建ngx_array_t结构体后创建数组
ngx_array_destroy 销毁数组
ngx_array_push 在数组中压入一个数据,得到一个数据指针,在这里就不用再分配内存了,可以直接使用分配的内存

ngx_array_push_n 在数组中压入 n个数据,得到一个数据指针,在这里就不用再分配内存了,可以直接使用分配的内存

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics