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

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

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

    下面是摘自 Google Code 的 Murmurhash 开源项目主页上的 Murmurhash2,Nginx 就是采用的这个. uint32_t MurmurHash2 ( const void ...

  2. Nginx 源码完全注释(11)ngx_spinlock

    Nginx 是多进程模式的,一个 master 与多个 workers,一般工作在多核 CPU 上,所以自旋锁就是必须用到的.Nginx 中的自旋锁的定义,位于 ngx_spinlock.c 中,如下 ...

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

    数组头文件 ngx_array.h #include <ngx_config.h> #include <ngx_core.h> struct ngx_array_s { voi ...

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

    首先看 ngx_alloc.h 文件,主要声明或宏定义了 ngx_alloc,ngx_calloc,ngx_memalign,ngx_free. /* * Copyright (C) Igor Sys ...

  5. 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 Windo ...

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

    队列头文件ngx_queue.h #include <ngx_config.h> #include <ngx_core.h> #ifndef _NGX_QUEUE_H_INCL ...

  7. Nginx 源码完全注释(10)ngx_radix_tree

    ngx_radix_tree.h // 未被使用的节点 #define NGX_RADIX_NO_VALUE (uintptr_t) -1 typedef struct ngx_radix_node_ ...

  8. Nginx源码完全注释(9)nginx.c: ngx_get_options

    本文分析 ngxin.c 中的 ngx_get_options 函数,其影响: nginx.c 中的: static ngx_uint_t ngx_show_help; static ngx_uint ...

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

    errno.h中的strerror(int errno)可以确定指定的errno的错误的提示信息.在 Nginx 中,将所有错误提示信息预先存储在一个数组里,而预先确定这个数组的大小,是在自动化脚本中 ...

随机推荐

  1. webpack libray 参考例子

    备注:   使用webpack 进行模块导出,方便进行通信 1. 项目初始化 ├── main.js ├── package.json ├── show.js ├── webpack.config.j ...

  2. minio 介绍

      minio 兼容Amason的S3分布式对象存储项目,采用Golang实现,客户端支持Java,Python,Javacript, Golang语言. Minio可以做为云存储的解决方案用来保存海 ...

  3. Apache Kafka 0.9消费者客户端

    当Kafka最初创建时,它与Scala生产者和消费者客户端一起运送.随着时间的推移,我们开始意识到这些API的许多限制.例如,我们有一个“高级”消费者API,它支持消费者组并处理故障转移,但不支持许多 ...

  4. Liveqrcode活码系统设计

    活码是一种二维码,可以通过后台配置让用户扫码时跳转到不同的网址.除了二维码生成接口,本站还实现了多租户的活码配置接口,以及活码后台jar包,详见二维码接口. 二维码生成使用了zxing三方包实现,活码 ...

  5. FPGA与DSP简单比较

    FPGA与DSP比较 两者的优势不一样.在硬件层面,DSP是ASIC,如同CPU GPU一样,适宜于量产降低成本,缺点是(硬件)设计一旦确定,便不易于修改. 而FPGA较灵活,可以通过硬件描述语言进行 ...

  6. 由 MySQL server 和 mysql-connector 版本的不匹配引发的一场惊魂

    剧情还原 今天原计划给领导演示一个小Demo, 昨天在自己机器上调通OK以后就下班了... 今天上午早会后,领导说 “昨天,我让我们IT同事把新的测试环境搭建好了,XXX 你把要演示的Demo部署到上 ...

  7. Java toString()方法

    JDK API java.lang 的Object类中的toString()方法 toString public String toString() 返回该对象的字符串表示.通常,toString 方 ...

  8. Apache 的编译安装

    直接看步骤: 1.安装必备环境:gcc.pcre .................................. 2.安装apr.apr-util 3.解压编译安装Apache: ./confi ...

  9. 你知道的,javascript语言的执行环境是"单线程模式",这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行,因此很多时候需要进行“异步模式”,请列举js异步编程的方法。

    回调函数,这是异步编程最基本的方法. 事件监听,另一种思路是采用事件驱动模式.任务的执行不取决于代码的顺序,而取决于某个事件是否发生. 发布/订阅,上一节的"事件",完全可以理解成 ...

  10. png格式图片转为svg格式图片

    png格式图片转为svg格式图片 (2012-08-30 16:24:00) 转载▼ 标签: 杂谈 分类: linux 在ubuntu下将png格式的图片转换成svg格式步骤如下:1.安装 inksc ...