讀 nginx 原始碼 ngx list

2021-09-24 08:06:31 字數 1970 閱讀 6481

c 語言並未提供像 c++ 一樣的 std 標準庫,所以很多類似 list、變長陣列、map 等常見的資料結構都需要自己實現。

鍊錶使用指標將不同的記憶體位址相互關聯,往往用於管理不連續記憶體,相對於陣列,其記憶體管理更加靈活。今天讓我們先看一下 nginx 中單向鍊錶 list 的實現。

typedef

struct

ngx_list_part_s

ngx_list_part_t;

// ngx_list_part_s 是一片連續記憶體,ngx_list_t 將多個 ngx_list_part_s 鏈結起來

// 也就是說 ngx_list_t 中的 node 其實是 ngx_list_part_s

struct

ngx_list_part_s ;

typedef

struct ngx_list_t;

// 建立乙個 ngx_list_t

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

// 插入乙個元素

void *ngx_list_push

(ngx_list_t *list)

;複製**

ngx_list_t 本身其實是通過單向鍊錶的形式來管理乙個個的 ngx_list_part_s 結構體,ngx_list_part_s 則管理一片連續的記憶體(大小一但申請就不會變化)。每當呼叫 ngx_list_push 插入元素到 ngx_list_t 中,就會從 ngx_list_part_s 的空間中分配。

/*

建立乙個 ngx_list_t,其中 n 為每個 ngx_list_part_s 中元素的個數,size 為這些元素的記憶體大小

*/ngx_list_t *

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

// 為 ngx_list_part_s 鍊錶中的 head 元素申請記憶體

list->part.elts = ngx_palloc(pool, n * size);

if (list->part.elts == null)

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)

// 申請 ngx_list_part_s 存放物件的記憶體

last->elts = ngx_palloc(l->pool, l->nalloc * l->size);

if (last->elts == null)

last->nelts = 0;

last->next = null;

// 將新的 ngx_list_part_s 插入到鍊錶尾端

l->last->next = last;

l->last = last;

}// 在 ngx_list_part_s 中分配乙個元素

elt = (char *) last->elts + l->size * last->nelts;

last->nelts++;

return elt;

}複製**

不同於常見的 list,ngx_list_t 中每個 node 是乙個一片的連續記憶體,可以理解為乙個個陣列通過 next 指標相連。這樣做可以降低單次插入元素的成本,但是卻存在一定程度上的浪費空間。

讀HashSet原始碼

先看建構函式 public hashset public hashset int initialcapacity public hashset int initialcapacity,float loadfactor 這個構造方法不是public的,僅用於linkedhashset.hashset ...

讀LockSupport原始碼

locksupport類是其他類實現鎖和同步的基礎 basic thread blocking primitives for creating locks and other synchronization classes.讀了原始碼就會知道,這個類主要利用了unsafe類中提供的part和unpa...

nginx原始碼分析 從原始碼看nginx框架總結

nginx原始碼總結 1 中沒有特別繞特別彆扭的編碼實現,從變數的定義呼叫函式的實現封裝,都非常恰當,比如從函式命名或者變數命名就可以看出來定義的大體意義,函式的基本功能,再好的架構實現在編碼習慣差的人實現也會黯然失色,如果透徹理解 的實現,領悟架構的設計初衷,覺得每塊 就想經過耐心雕琢一樣,不僅僅...