Redis原始碼剖析 雙端鍊錶Sdlist

2021-07-25 06:56:36 字數 3603 閱讀 4656

redis為雙端鍊錶的每乙個節點定義了如下的結構體。

// 鍊錶節點定義

typedef

struct listnode listnode;

與一般的雙端鍊錶無異,定義了鍊錶節點的結構體之後,下面就定義鍊錶的結構體,用來方便管理鍊錶節點,其結構體定義如下:
typedef

struct

list list;

redis在實現鍊錶的時候,定義其為雙端無環鏈表,其示意圖如下:

此外,redis對其結構體提供了一系列的巨集定義函式,方便操作其結構體引數

#define listlength(l) ((l)->len)  // 獲取list長度

#define listfirst(l) ((l)->head) // 獲取list頭節點指標

#define listlast(l) ((l)->tail) // 獲取list尾節點指標

#define listprevnode(n) ((n)->prev) // 獲取當前節點前乙個節點

#define listnextnode(n) ((n)->next) // 獲取當前節點後乙個節點

#define listnodevalue(n) ((n)->value) // 獲取當前節點的值

#define listsetdupmethod(l,m) ((l)->dup = (m)) // 設定節點值複製函式

#define listsetfreemethod(l,m) ((l)->free = (m)) // 設定節點值釋放函式

#define listsetmatchmethod(l,m) ((l)->match = (m)) // 設定節點值匹配函式

#define listgetdupmethod(l) ((l)->dup) // 獲取節點值賦值函式

#define listgetfree(l) ((l)->free) // 獲取節點值釋放函式

#define listgetmatchmethod(l) ((l)->match) // 獲取節點值匹配函式

redis為sdlist定義了乙個迭代器結構,其能正序和逆序的訪問list結構。

typedef

struct listiter listiter;

對於direction引數,redis提供了兩個巨集定義

#define al_start_head 0  // 從頭到尾

#define al_start_tail 1 // 從尾到頭

sdlist提供了listcreate函式來建立乙個空的鍊錶。

list *listcreate(void)

sdlist提供了listrelease函式來釋放整個鍊錶

void listrelease(list *list)

zfree(list); // 釋放煉表頭

}

sdlist提供了三個函式來完成向list中插入乙個節點的功能。

// 該函式向list的頭部插入乙個節點

list *listaddnodehead(list *list, void *value)

else

list->len++; // 長度+1

return

list;

}

// 該函式可以在list的尾部新增乙個節點

list *listaddnodetail(list *list, void *value)

else

list->len++; // 長度+1

return

list;

}

// 向任意位置插入節點

// 其中,old_node為插入位置

// value為插入節點的值

// after為0時表示插在old_node前面,為1時表示插在old_node後面

list *listinsertnode(list *list, listnode *old_node, void *value, int after)

} else

}if (node->prev != null)

if (node->next != null)

list->len++;

return

list;

}

void listdelnode(list *list, listnode *node)

sdlist為其迭代器提供了一些操作,用來完成獲取迭代器,釋放迭代器,重置迭代器,獲取下乙個迭代器等操作,具體原始碼見如下分析。

listiter *listgetiterator(list *list, int direction)

void listreleaseiterator(listiter *iter)
重置迭代器分為兩種,一種是重置正向迭代器,一種是重置為逆向迭代器

// 重置為正向迭代器

void listrewind(list *list, listiter *li)

// 重置為逆向迭代器

void listrewindtail(list *list, listiter *li)

// 根據direction屬性來獲取下乙個迭代器

listnode *listnext(listiter *iter)

return current;

}

sdlist提供了listdup函式,用於複製整個鍊錶。

list *listdup(list *orig)

} else

// 如果沒有則直接賦值

value = node->value;

// 依次向尾部新增節點

if (listaddnodetail(copy, value) == null)

}return copy;

}

sdlist提供了兩種查詢函式。其一是根據給定節點值,在鍊錶中查詢該節點

listnode *listsearchkey(list *list, void *key)

} else }}

// 沒有找到就返回null

return null;

}

其二是根據序號來查詢節點

listnode *listindex(list *list, long index)  else 

return n;

}

旋轉操作其實就是講表尾節點移除,然後插入到表頭,成為新的表頭

void listrotate(list *list)

redis6 0原始碼雙端鍊錶

在redis中列表鍵,發布和訂閱 慢查詢 監視器等都用到了鍊錶,redis伺服器本身還是用鍊錶來儲存多個客戶端的狀態資訊,以及使用鍊錶來構建客戶端輸出緩衝區。鍊錶節點adlist.h listnode typedef struct listnode listnode typedef struct l...

Redis原始碼剖析(八)鍊錶

在之前對redis的介紹中,可以看到鍊錶的使用頻率非常高。鍊錶可以作為單獨的儲存結構,比如客戶端的監視鍊錶記錄該客戶端監視的所有鍵,伺服器的模式訂閱鍊錶記錄所有客戶端和它的模式訂閱。鍊錶也可以內嵌到字典中作為字典的值型別,比如資料庫的監視字典使用鍊錶儲存監視某個鍵的所有客戶端,伺服器的訂閱字典使用鍊...

redis 雙端鍊錶

鍊錶作為陣列之外的一種常用序列抽象,是大多數高階語言的基本資料型別,因為c 語言本身不支援鍊錶型別,大部分c 程式都會自己實現一種鍊錶型別,redis 也不例外.雙端鍊錶的應用 雙端鍊錶作為一種通用的資料結構,在redis 內部使用得非常多 它既是redis 列表結構的底層實現之一,還被大量redi...