redis源码阅读-adlist

adlist 阅读

author: Pei Xingxin ([email protected])

background

这里其实想谈谈为什么要做redis的source code reading & analysing。动机有点尴尬,因为在大厂的工作中,开源的工具使用较少,时间长了竟然会成为一个被外部人员低看一眼的理由。当然,对于面试应该考察什么这个话题,我也一肚子槽想吐,找个机会会一并写出。

话不多说,言归正传

adlist是什么

adlist - A generic doubly linked list implementation,就是一个通用的双向列表实现。

adlist的数据结构

一个典型的list,一定会有node,这个实现比较完备,同时提供了iterator。于是这里至少有三个数据结构

listNode

Node是链表中的每个节点的定义与抽象,其中value可以是更丰富的类型

typedef struct listNode {
    struct listNode *prev;
    struct listNode *next;
    void *value;
} listNode;

listIter

迭代器用于遍历整个list

typedef struct listIter {
    listNode *next;
    int direction;
} listIter;

list

list是真正对外操作的数据结构,有几个重要的参数,head,tail用于分别表示头节点和尾节点,len是用于记录当前的链表长度,这样length操作就是O(1)的时间复杂度。另外,为了使链表更有通用性,即基于value的复杂性,提供了dup,free,match三个特殊的函数指针用于专门操作value部分

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操作部分,宏部分

这部分操作是可以根据list的成员变量直接获得的,定义函数的好处是,接口更统一易读

    /* Functions implemented as macros */
    #define listLength(l) ((l)->len)
    #define listFirst(l) ((l)->head)
    #define listLast(l) ((l)->tail)
    #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)

iterator的操作方向,也是宏定义

/* Directions for iterators */
#define AL_START_HEAD 0
#define AL_START_TAIL 1

函数操作的部分,需要代码实现部分的对于接口定义

接口的定义基本上都非常的通俗易懂,大部分其意自明。这里重点描述一下几个函数

listRewind,  表示把迭代器指向头部,并且从头部开始遍历
listRewindTail,把迭代器指向尾部,遍历方向设置为从尾部开始
listRotate,表示把最后一个元素挪到第一个去
listSearchKey,表示在链表中找到value = key 的节点
listIndex,表示链表从头或者从尾部,找到第index个节点

/* Prototypes */
list *listCreate(void);
void listRelease(list *list);
list *listAddNodeHead(list *list, void *value);
list *listAddNodeTail(list *list, void *value);
list *listInsertNode(list *list, listNode *old_node, void *value, int after);
void listDelNode(list *list, listNode *node);
listIter *listGetIterator(list *list, int direction);
listNode *listNext(listIter *iter);
void listReleaseIterator(listIter *iter);
list *listDup(list *orig);
listNode *listSearchKey(list *list, void *key);
listNode *listIndex(list *list, long index);
void listRewind(list *list, listIter *li);
void listRewindTail(list *list, listIter *li);
void listRotate(list *list);

函数操作的实现部分

这部分都在adlist.c中,代码实现很优美,建议日常的链表操作都可以参考这里代码实现。举一个实现比较优雅的例子

listNode *listNext(listIter *iter)
{
    listNode *current = iter->next;

    if (current != NULL) {
        if (iter->direction == AL_START_HEAD)
            iter->next = current->next;
        else
            iter->next = current->prev;
    }
    return current;
}

你可能感兴趣的:(redis源码阅读-adlist)