Nginx原始碼完全註釋(3)ngx_list.h / ngx_list.c

鍾超發表於2012-09-09

Nginx原始碼完全註釋(3)ngx_list.h / ngx_list.c

  • 作者:柳大·Poechant(鍾超)
  • 郵箱:zhongchao.ustc#gmail.com(# -> @)
  • 部落格:Blog.CSDN.net/Poechant
  • 日期:August 16th, 2012

列表標頭檔案ngx_list.h


#ifndef _NGX_LIST_H_INCLUDED_
#define _NGX_LIST_H_INCLUDED_

#include <ngx_config.h>
#include <ngx_core.h>

typedef struct ngx_list_part_s  ngx_list_part_t;

// 一個 part 相當於列表的一個節點
struct ngx_list_part_s {
    void             *elts; // 資料儲存區
    ngx_uint_t        nelts; // 已儲存元素個數
    ngx_list_part_t  *next; //下一個 part
};

// 列表定義
typedef struct {
    ngx_list_part_t  *last; // 最後一個part的位置
    ngx_list_part_t   part; // 表頭
    size_t            size;
    ngx_uint_t        nalloc; // 列表單個節點的最大元素數
    ngx_pool_t       *pool; // 記憶體池
} ngx_list_t;


ngx_list_t *ngx_list_create(ngx_pool_t *pool, ngx_uint_t n, size_t size);

static ngx_inline ngx_int_t
ngx_list_init(ngx_list_t *list, ngx_pool_t *pool, ngx_uint_t n, size_t size)
{
    // 為 list 的第一個元素的資料儲存區分配 n * size 的大小
    list->part.elts = ngx_palloc(pool, n * size); 
    if (list->part.elts == NULL) {
        return NGX_ERROR;
    }

    list->part.nelts = 0; // 已存元素數為 0
    list->part.next = NULL;
    list->last = &list->part; // 當前可用,就是表頭節點
    list->size = size; // 列表每個節點的每個元素的大小(位元組數)
    list->nalloc = n; // 列表單個節點的最大元素個數
    list->pool = pool; // 記憶體池

    return NGX_OK;
}

// 列表的每個節點都是一樣大的(一樣的元素數,每個元素大小一樣)

/*
 *
 *  the iteration through the list:
 *
 *  part = &list.part;
 *  data = part->elts;
 *
 *  for (i = 0 ;; i++) {
 *
 *      if (i >= part->nelts) {
 *          if (part->next == NULL) {
 *              break;
 *          }
 *
 *          part = part->next;
 *          data = part->elts;
 *          i = 0;
 *      }
 *
 *      ...  data[i] ...
 *
 *  }
 */

void *ngx_list_push(ngx_list_t *list);

#endif /* _NGX_LIST_H_INCLUDED_ */

列表原始檔ngx_list.c


#include <ngx_config.h>
#include <ngx_core.h>

ngx_list_t *
ngx_list_create(ngx_pool_t *pool, ngx_uint_t n, size_t size)
{
    ngx_list_t  *list;

    // 連結串列定義
    list = ngx_palloc(pool, sizeof(ngx_list_t));
    if (list == NULL) {
        return NULL;
    }

    // 連結串列表頭節點的資料儲存區
    list->part.elts = ngx_palloc(pool, n * size);
    if (list->part.elts == NULL) {
        return NULL;
    }

    // 連結串列表頭節點的已存元素數為 0
    list->part.nelts = 0;
    list->part.next = NULL;
    list->last = &list->part;
    list->size = size;
    list->nalloc = n;
    list->pool = pool;

    // 返回這個建立好的列表
    return list;
}

// 插入一個元素到列表中
void *
ngx_list_push(ngx_list_t *l)
{
    void             *elt;
    ngx_list_part_t  *last;

    last = l->last;

    // 最後一個節點的已存元素數 == 列表的單個節點的最大元素數,就是需要分配新節點了
    if (last->nelts == l->nalloc) {

        /* the last part is full, allocate a new list part */

        // 從列表的記憶體池,分配一個節點出來給 last
        last = ngx_palloc(l->pool, sizeof(ngx_list_part_t));
        if (last == NULL) {
            return NULL;
        }

        // 從列表的記憶體池,分配空間給最後一個節點的資料儲存區
        last->elts = ngx_palloc(l->pool, l->nalloc * l->size);
        if (last->elts == NULL) {
            return NULL;
        }

        // 最後一個節點的已存元素數為 0
        last->nelts = 0;
        last->next = NULL;

        // 新搞出來這個節點,接到最後一個節點後邊
        l->last->next = last;
        // 把這個新節點當成最後一個節點
        l->last = last;
    }

    // 最後一個節點的資料儲存區起始位置 + 元素大小 * 最後節點的已存元素數
    // 就是下一個可以放元素的位置
    elt = (char *) last->elts + l->size * last->nelts;
    
    // 最後一個節點的已存元素數加1
    last->nelts++;

    // 返回下一個可以放元素的位置
    return elt;
}

從上面可以看出,create 是從 pool 分配定義 list 結構的記憶體,分配表頭節點的記憶體。init 是初始化已有的 list。

Reference

  1. http://blog.csdn.net/v_july_v/article/details/7040425
  2. http://www.cnblogs.com/sld666666/archive/2010/06/27/1766255.html
  3. http://www.cnblogs.com/jzhlin/archive/2012/06/05/Nginx_pool.html
  4. http://code.google.com/p/nginxsrp/wiki/NginxCodeReview#ngx的記憶體池

-

轉載請註明來自柳大Poechant(鍾超Michael)的CSDN部落格:

鍾超Michael的部落格:Blog.CSDN.net/Poechant

鍾超Michael的微博:鍾超Michael的新浪微博

-

相關文章