Nginx源码完全注释(3)ngx_list.h / ngx_list.c

列表头文件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。

时间: 2024-08-30 09:48:15

Nginx源码完全注释(3)ngx_list.h / ngx_list.c的相关文章

Nginx源码完全注释(6)core/murmurhash

下面是摘自 Google Code 的 Murmurhash 开源项目主页上的 Murmurhash2,Nginx 就是采用的这个. uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed ) { // 'm' and 'r' are mixing constants generated offline. // They're not really 'magic', they just happen to work well

Nginx 源码完全注释(11)ngx_spinlock

Nginx 是多进程模式的,一个 master 与多个 workers,一般工作在多核 CPU 上,所以自旋锁就是必须用到的.Nginx 中的自旋锁的定义,位于 ngx_spinlock.c 中,如下: void ngx_spinlock(ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin) { #if (NGX_HAVE_ATOMIC_OPS) ngx_uint_t i, n; for ( ;; ) { // lock 即为锁

Nginx源码完全注释(2)ngx_array.h / ngx_array.c

数组头文件 ngx_array.h #include <ngx_config.h> #include <ngx_core.h> 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); vo

nginx源码完全注释(1)ngx_alloc.h / ngx_alloc.c

首先看 ngx_alloc.h 文件,主要声明或宏定义了 ngx_alloc,ngx_calloc,ngx_memalign,ngx_free. /* * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. */ #ifndef _NGX_ALLOC_H_INCLUDED_ #define _NGX_ALLOC_H_INCLUDED_ #include #include void *ngx_alloc(size_t size, ngx_lo

Nginx源码完全注释(4)ngx_queue.h / ngx_queue.c

队列头文件ngx_queue.h #include <ngx_config.h> #include <ngx_core.h> #ifndef _NGX_QUEUE_H_INCLUDED_ #define _NGX_QUEUE_H_INCLUDED_ typedef struct ngx_queue_s ngx_queue_t; // 队列的节点,也直接表示队列.注意这是一个双向循环队列 struct ngx_queue_s { ngx_queue_t *prev; ngx_queu

Nginx源码完全注释(7)ngx_palloc.h/ngx_palloc.c

ngx_palloc.h /* * NGX_MAX_ALLOC_FROM_POOL should be (ngx_pagesize - 1), i.e. 4095 on x86. * On Windows NT it decreases a number of locked pages in a kernel. */ #define NGX_MAX_ALLOC_FROM_POOL (ngx_pagesize - 1) #define NGX_DEFAULT_POOL_SIZE (16 * 102

Nginx源码完全注释(8)ngx_errno.c

errno.h中的strerror(int errno)可以确定指定的errno的错误的提示信息.在 Nginx 中,将所有错误提示信息预先存储在一个数组里,而预先确定这个数组的大小,是在自动化脚本中完成的,如下是auto/unix脚本:(其中自动化脚本auto/feature的作用参考<解剖 Nginx·自动脚本篇(4)工具型脚本系列>一文) // auto/unix ngx_feature="sys_nerr" ngx_feature_name="NGX_SY

Nginx 源码完全注释(10)ngx_radix_tree

ngx_radix_tree.h // 未被使用的节点 #define NGX_RADIX_NO_VALUE (uintptr_t) -1 typedef struct ngx_radix_node_s ngx_radix_node_t; struct ngx_radix_node_s { ngx_radix_node_t *right; // 右子树的根节点 ngx_radix_node_t *left; // 左子树的根节点 ngx_radix_node_t *parent; // 父节点

Nginx源码完全注释(5)core/ngx_cpuinfo.c

/* * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. */ #include <ngx_config.h> #include <ngx_core.h> // 如果 CPU 架构是 i386 或 amd64,并且编译器是 GNU Compiler 或 Intel Compiler,则定义 cngx_puid 函数 // 否则 ngx_cpuid 函数为空 #if (( __i386__ || __amd64__ ) &a