动态数组
这玩意吧,应该最简单的一个。
动态数组有以下特征:
- 访问速度快。
- 允许元素的个数具体不确定性。也就说是可以动态扩充数组
在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;
}
/*
* 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$