这是普通的链表实现, 链表结点不直接持有数据, 而是通过void *
指针来间接的指向数据. 其实现位于 src/adlist.h
与src/adlist.c
中, 关键定义如下:
typedef struct listNode {
struct listNode *prev;
struct listNode *next;
void *value;
} listNode;
typedef struct listIter {
listNode *next;
int direction;
} listIter;
typedef struct list {
listNode *head;
listNode *tail;
void *(*dup)(void *ptr);
void (*free)(void *ptr);
int (*match)(void *ptr, void *key);
unsigned long len;
} list;
其内存布局如下图所示:
这是一个平平无奇的链表的实现. list
在Redis除了作为一些Value Type的底层实现外, 还广泛用于Redis的其它功能实现中, 作为一种数据结构工具使用. 在list
的实现中, 除了基本的链表定义外, 还额外增加了:
- 迭代器
listIter
的定义, 与相关接口的实现. - 由于
list
中的链表结点本身并不直接持有数据, 而是通过value
字段, 以void *
指针的形式间接持有, 所以数据的生命周期并不完全与链表及其结点一致. 这给了list
的使用者相当大的灵活性. 比如可以多个结点持有同一份数据的地址. 但与此同时, 在对链表进行销毁, 结点复制以及查找匹配时, 就需要list
的使用者将相关的函数指针赋值于list.dup
,list.free
,list.match
字段.