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

来源:互联网 发布:淘宝vip专享活动 编辑:程序博客网 时间:2024/06/16 23:11

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 5int 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 intngx_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 5typedef struct{    int i;    double j;}element;static voidprintTheArray(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 5the value i is0the value i is1the value i is2the value i is3the value i is4

array其实就是动态扩张的数据结构,每次内存不够用时,重新申请2倍的内存使用.跟STL的设计差不多.

原创粉丝点击