您的位置:首页 > 理论基础 > 数据结构算法

nginx源码阅读笔记.array和list数据结构

2017-10-18 22:13 513 查看
1.概述

nginx中,array和list 的实现 和queue的实现不同,queue的实现是不依赖于具体的结构的,可以申明任何结构体只要该结构体中间含有queue的实例就可以将它们组织起来,那么queue的对象的内存分配需要(用户自己申请),在分配的包含queue的对象时已经分配好,

而list和array 的实现则时初始化一个list或者array, 自定义的结构的内存分配任务交给list和array完成,在向list 和array插入的时候就返回容器向内存申请的内存,用户直接可以在该地址上完成操作.

2.代码

#include <stdlib.h>
typedef unsigned int u_int;
typedef struct ngx_list_part_s ngx_list_part_t;
typedef struct ngx_list_s ngx_list_t;

struct ngx_list_part_s{
void  *elts;
u_int nelts;
ngx_list_part_t *next;
};
struct ngx_list_s{
ngx_list_part_t *last;
ngx_list_part_t part;

u_int ele_size; //element size
u_int nalloc;   //element count each page;
};

static inline int
ngx_list_init(ngx_list_t* list,u_int sz,u_int n){
list->part.elts = malloc(sz * n);
if(list->part.elts == NULL)
return -1;
list->part.nelts = 0;
list->part.next = NULL;

list->ele_size = sz;
list->nalloc = n;
list->last = &(list->part);
return 1;
}

static ngx_list_t*
ngx_list_create(u_int sz,u_int n){
ngx_list_t* list = (ngx_list_t*) malloc(sizeof(ngx_list_t));
if(list == NULL)
return NULL;
if(ngx_list_init(list,sz,n) < 0){
free(list);
return NULL;
}
return list;
}
static void*
ngx_push_back(ngx_list_t* list){
void* elts;
ngx_list_part_t* last;
last = list->last;
if(last->nelts == list->nalloc){
ngx_list_part_t *n = (ngx_list_part_t*) malloc(sizeof(ngx_list_part_t));
if(n == NULL){
return NULL;
}
n->elts = malloc(list->ele_size*list->nalloc);
if(n->elts == NULL){
free(n);
return NULL;
}
n->nelts = 0;
n->next = NULL;
last->next = n;
list->last = n;
last = n;
}
elts = (char*)(last->elts) + list->ele_size*last->nelts;
last->nelts++;
return elts;
}
typedef struct myElement{
int i;
double j;
} element;
#define NELEM 5
int main(){
ngx_list_t *mylist = ngx_list_create(sizeof(element), NELEM);
for(int i =0; i < 2*NELEM; i++){
element* p = (element*)ngx_push_back(mylist);
p->i = i;
p->j = i;
}
}


代码只管分配内存,而没有管内存的回收,nginx中有专门的内存池帮助系统回收内存,

list 其实是很多页内存通过链表连接起来的,每一页的大小相同,当一页占满时,就向系统申请多一页,链在后面,

#include <stdio.h>
#include <stdlib.h>
typedef unsigned int u_int;
typedef struct{
void* elts;
u_int nelts;
u_int size;
u_int nalloc; //current reserved, nelts <= nalloc
}ngx_array_t;

static inline int
ngx_array_init(ngx_array_t* array,u_int sz,u_int nalloc){
array->nelts = 0;
array->size = sz;
array->nalloc =nalloc;
array->elts = malloc( sz* nalloc);
if(array->elts == NULL)
return -1;
return 1;
}
static ngx_array_t*
ngx_array_create(u_int sz, u_int nalloc){
ngx_array_t* ret = (ngx_array_t*) malloc(sizeof(ngx_array_t));
if(ret == NULL)
return NULL;
if(ngx_array_init(ret,sz,nalloc) == -1){
free(ret);
return NULL;
}
return ret;
}
static void*
ngx_array_push(ngx_array_t *a){
if(a->nelts == a->nalloc){
u_int nelts = (a->nelts == 0)? 1 : 2*(a->nelts);
void* new_nelts = realloc(a->elts,nelts);
if(new_nelts == NULL)
return NULL;
a->elts = new_nelts;
a->nalloc = nelts;
}
void* ret = (char*)a->elts + a->size*a->nelts;
a->nelts++;
return ret;
}
#define ARRAYSIZE 5
typedef struct{
int i;
double j;
}element;
static void
printTheArray(ngx_array_t *a){
int i;
element* p = NULL;
int nelts = a->nelts;
printf("the sapce is %d\n",a->nalloc);
for(i = 0; i < nelts;i++){
p = (element*)((char*)a->elts + i*sizeof(element));
printf("the value i is%d\n",p->i);
}

}

int main(){
ngx_array_t *array = ngx_array_create(sizeof(element),ARRAYSIZE);
if(array == NULL)
return 0;
for(int i =0; i < ARRAYSIZE;i++){
element *p =(element*)ngx_array_push(array);
p->i = i;
p->j = i;
}
printTheArray(array);
return 0;

}


运行结果:

the sapce is 5
the value i is0
the value i is1
the value i is2
the value i is3
the value i is4


array其实就是动态扩张的数据结构,每次内存不够用时,重新申请2倍的内存使用.跟STL的设计差不多.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: