nginx 源码:动态数组

动态数组

这玩意吧,应该最简单的一个。
动态数组有以下特征:
  1. 访问速度快。
  2. 允许元素的个数具体不确定性。也就说是可以动态扩充数组
在ngnix中,动态数组的内存是通过向ngnix的内存池内申请的,所以动态扩充数组的时候特别方便,由ngnix统一管理。

动态数组的结构和方法

动态数组的结构

struct ngx_array_s {
    void        *elts; //指向首地址
    ngx_uint_t   nelts;//数组中已经使用了的个数
    size_t       size;//每个元素占用内存的大小
    ngx_uint_t   nalloc;//当前数组中能内容多少个元素个数
    ngx_pool_t  *pool;//用于分配内存池
};

支持的方法和实现

这是头文件部分的内容,ngx_array.c里面会有具体函数的实现
/*创建一个动态数组,只用传入需要每个元素的大小和需要多少个元素,会返回一个指向ngx_array_t的指针,下面的方法都需要它*/
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);
/*放入n个元素*/
void *ngx_array_push_n(ngx_array_t *a, ngx_uint_t n);

/*初始化一个动态数组,那么创建了可以不用初始化,初始化相当于重置*/
static  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;
}

ngx_array.c文件,没什么难点,轻轻松松看懂:
/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */

#include "mytest_ngx_core.h"

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;
    /*从下面的代码来看,删除内存就是改改d.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;
    }
}


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)
        {
            /*
             * the array allocation is the last in the pool
             * and there is space for new allocation
             *
             * zy:这样的情况下只增加了一个元素
             */

            p->d.last += a->size;//这里只增加了一个元素的位置
            a->nalloc++;//相应能够容纳的个数也会增加

        } else {
            /* allocate a new array
             * zy:此种情况下翻倍
             * */

            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;
}


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
             * zy:这样的情况下只是需要多少新内存,就给的多少内存
             */

            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;
}

运行的小例子

为了运行小例子,还需要调用有关内存池的一些方法,这里就没贴涉及内存的源码了,所以说也许在拷贝这几个文档也不能用,只能参考一下。

main

#include "mytest_ngx_core.h"

typedef struct {
    u_char *data;
    int num;
}TestNode;

int main() {
	ngx_pool_t *pool=ngx_create_pool(16384);
	ngx_array_t *dynamicArray=ngx_array_create(pool,1,sizeof(TestNode));
	/*注意添加元素的方式*/
	TestNode* a=ngx_array_push(dynamicArray);
	a->num=1;
	a=ngx_array_push(dynamicArray);
	a->num=2;
	TestNode* b=ngx_array_push_n(dynamicArray,3);
	b->num=3;
	(b+1)->num=4;
	(b+2)->num=5;

	TestNode *nodeArray=dynamicArray->elts;
	ngx_uint_t arraySeq=0;
	for(;arraySeq<dynamicArray->nelts;arraySeq++){
		a=nodeArray+arraySeq;
		printf("%d\n",a->num);
	}

}



ngx_array.h

/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */
#include "mytest_ngx_core.h"//为了能够运行例子,我自己写的,包括hash表和动态数组

#ifndef _NGX_ARRAY_H_INCLUDED_
#define _NGX_ARRAY_H_INCLUDED_


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);
/*摧毁一个*/
void ngx_array_destroy(ngx_array_t *a);
/*放入一个元素*/
void *ngx_array_push(ngx_array_t *a);
/*放入n个元素*/
void *ngx_array_push_n(ngx_array_t *a, ngx_uint_t n);

/*初始化一个动态数组,那么创建了可以不用初始化,初始化相当于重置*/
static  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;
}


#endif /* _NGX_ARRAY_H_INCLUDED_ */


ngx_array.c

/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */

#include "mytest_ngx_core.h"

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;
    /*从下面的代码来看,删除内存就是改改d.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;
    }
}


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)
        {
            /*
             * the array allocation is the last in the pool
             * and there is space for new allocation
             *
             * zy:这样的情况下只增加了一个元素
             */

            p->d.last += a->size;//这里只增加了一个元素的位置
            a->nalloc++;//相应能够容纳的个数也会增加

        } else {
            /* allocate a new array
             * zy:此种情况下翻倍
             * */

            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;
}


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
             * zy:这样的情况下只是需要多少新内存,就给的多少内存
             */

            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;
}


mytest_ngx_core.h

/*
 * mytest_ngx_core.h
 *	这我写的类似于ngx_core.h
 *	这个ngx_core.h里面包含了很都头文件,给很多变量取了别名
 *	这样别的文件只用包含这个头文件就好了
 *  Created on: Apr 1, 2014
 *      Author: zy
 */


#ifndef MYTEST_NGX_CORE_H_
#define MYTEST_NGX_CORE_H_
/*宏使得到的内存地址为NGX_ALIGNMENT的倍数。数据对齐,可以避免cpu取值时,要进行两次IO */
#define ngx_align_ptr(p, a)                                                   \
    (u_char *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1))


#ifndef NGX_ALIGNMENT
#define NGX_ALIGNMENT   sizeof(unsigned long)    /* platform word */
#endif

#define  NGX_OK          0
#define  NGX_ERROR      -1
#define  NGX_AGAIN      -2
#define  NGX_BUSY       -3
#define  NGX_DONE       -4
#define  NGX_DECLINED   -5
#define  NGX_ABORT      -6
#define ngx_cacheline_size 32	//内存中对齐的要求,能够更快的找到对应的位置,我是32位的机子,所以我设置为这个值。
								//但不是书写的,是我参考了很多网页猜出来的

typedef unsigned short u_short;

typedef unsigned int ngx_uint_t;
typedef  unsigned char u_char;


typedef long int ngx_int_t;
typedef struct ngx_pool_s        ngx_pool_t;
typedef struct ngx_array_s       ngx_array_t;
typedef unsigned long int  uintptr_t;
#define ngx_memzero(buf, n)       (void) memset(buf, 0, n)
#define ngx_strlen(s)       strlen((const char *) s)
#define ngx_memcpy(dst, src, n)   (void) memcpy(dst, src, n)
#define ngx_align(d, a)     (((d) + (a - 1)) & ~(a - 1))
#define ngx_tolower(c)      (u_char) ((c >= 'A' && c <= 'Z') ? (c | 0x20) : c)
#define ngx_strncmp(s1, s2, n)  strncmp((const char *) s1, (const char *) s2, n)



#include <stdlib.h>
#include <stddef.h>
void
ngx_strlow(u_char *dst, u_char *src, size_t n)
{
    while (n) {
        *dst = ngx_tolower(*src);
        dst++;
        src++;
        n--;
    }
}

u_char *
ngx_cpystrn(u_char *dst, u_char *src, size_t n)
{
    if (n == 0) {
        return dst;
    }

    while (--n) {
        *dst = *src;

        if (*dst == '\0') {
            return dst;
        }

        dst++;
        src++;
    }

    *dst = '\0';

    return dst;
}
#include "ngx_palloc.h"
#include "ngx_array.h"
#include "ngx_hash.h"
#include "ngx_alloc.h"

#include "ngx_palloc.c"
#include "ngx_array.c"
#include "ngx_hash.c"
#include "ngx_alloc.c"


#endif /* MYTEST_NGX_CORE_H_ */

运行结果

asd@asd-desktop:~/workspace/test/src$ ./a.out 
1
2
3
4
5
asd@asd-desktop:~/workspace/test/src$ 




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值