nginx 源码:动态数组

来源:互联网 发布:rt809编程器使用方法 编辑:程序博客网 时间:2024/05/02 16:46

动态数组

这玩意吧,应该最简单的一个。
动态数组有以下特征:
  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_tngx_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;}voidngx_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_tngx_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;}voidngx_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>voidngx_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 12345asd@asd-desktop:~/workspace/test/src$ 




0 0
原创粉丝点击