一、引言

  之前了解到C++中的vector的时候没有怎么在意。现在阅读nginx源码时,发现了nginx中很多利用C语言对一些数据结构的实现,很不错。本文主要总结一下,nginx中可扩展数组的实现以及一个相关的sort接口。

二、数据结构

  C中数据结构是所有高级操作的基础,这里也不例外。

typedef struct {
    void        *elts;                      // 所有成员占用的总空间(n * sizeof(type)),会通过内存池分配
    ngx_uint_t   nelts;                     // 已经存在的成员的个数
    size_t       size;                      // 成员的sizeof
    ngx_uint_t   nalloc;                    // 数组容量的大小
    ngx_pool_t  *pool;                      // 数组相关的内存池的指针
} ngx_array_t;

  其实从数据结构基本就可以了解如何实现。

三、相关接口

  ngx_array_create:创建一个array,这里包括两步:

            1、创建一个ngx_array_t结构对象;

            2、根据初始设置的array容量、数据类型赋值nalloc和size,然后创建一个初始数组空间;

  ngx_array_push_n和ngx_array_push:向array中插入元素。如果空间可用就直接插入数据即可;如果空间不够那么就创建新的空间更大的array,然后将旧的数据memcpy到新的空间中。

四、其他

  该设计中涉及到nginx中比较巧妙的内存池设计,后面再说明。当然我们在实现时,不一定要采用内存池模式。ps:内存池的好处,都了解。

五、数组排序

  采用动态分配哨兵的插入排序法。

  

/*******************************************************************************
* 函数名称: ngx_sort
* 输入参数: base--数组的首地址;n--成员个数;size---元素空间的大小
* 输出参数: 
* 返 回 值: 
* 时    间: 2015-06-03
* 说    明: 排序操作接口,具体的比较条件和结果入参函数接口cmp决定
* 其    它: 为动态数组中的元素执行排序,排序法为: 插入排序法
*******************************************************************************/
void
ngx_sort(void *base, size_t n, size_t size,
    ngx_int_t (*cmp)(const void *, const void *))
{
    u_char  *p1, *p2, *p;

    p = ngx_alloc(size, ngx_cycle->log);        // 动态分配内存,作为哨兵节点
    if (p == NULL) {
        return;
    }

    /* 插入排序法: 将一条记录插入到一个有序的序列中 */
    for (p1 = (u_char *) base + size;           // 假设第一个元素就是有序表,所以从第二个开始
         p1 < (u_char *) base + n * size;       // 直到最后一个
         p1 += size)
    {
        ngx_memcpy(p, p1, size);        // 哨兵作为临时存储

        for (p2 = p1;
             p2 > (u_char *) base && cmp(p2 - size, p) > 0;     // 哨兵作为判断边界
             p2 -= size)
        {                       // 将
            ngx_memcpy(p2, p2 - size, size);
        }

        ngx_memcpy(p2, p, size);
    }

    ngx_free(p);
}