redis為雙端鍊錶的每乙個節點定義了如下的結構體。
與一般的雙端鍊錶無異,定義了鍊錶節點的結構體之後,下面就定義鍊錶的結構體,用來方便管理鍊錶節點,其結構體定義如下:// 鍊錶節點定義
typedef
struct listnode listnode;
redis在實現鍊錶的時候,定義其為雙端無環鏈表,其示意圖如下:typedef
struct
list list;
此外,redis對其結構體提供了一系列的巨集定義函式,方便操作其結構體引數
redis為sdlist定義了乙個迭代器結構,其能正序和逆序的訪問list結構。#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) // 獲取節點值匹配函式
對於direction引數,redis提供了兩個巨集定義typedef
struct listiter listiter;
sdlist提供了listcreate函式來建立乙個空的鍊錶。#define al_start_head 0 // 從頭到尾
#define al_start_tail 1 // 從尾到頭
sdlist提供了listrelease函式來釋放整個鍊錶list *listcreate(void)
sdlist提供了三個函式來完成向list中插入乙個節點的功能。void listrelease(list *list)
zfree(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;
}
sdlist為其迭代器提供了一些操作,用來完成獲取迭代器,釋放迭代器,重置迭代器,獲取下乙個迭代器等操作,具體原始碼見如下分析。void listdelnode(list *list, listnode *node)
listiter *listgetiterator(list *list, int direction)
void listreleaseiterator(listiter *iter)
重置迭代器分為兩種,一種是重置正向迭代器,一種是重置為逆向迭代器
// 重置為正向迭代器
void listrewind(list *list, listiter *li)
// 重置為逆向迭代器
void listrewindtail(list *list, listiter *li)
sdlist提供了listdup函式,用於複製整個鍊錶。// 根據direction屬性來獲取下乙個迭代器
listnode *listnext(listiter *iter)
return current;
}
sdlist提供了兩種查詢函式。其一是根據給定節點值,在鍊錶中查詢該節點list *listdup(list *orig)
} else
// 如果沒有則直接賦值
value = node->value;
// 依次向尾部新增節點
if (listaddnodetail(copy, value) == null)
}return copy;
}
其二是根據序號來查詢節點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...