Redis源码学习(1):adlist

来源:互联网 发布:关于网络暴力的演讲稿 编辑:程序博客网 时间:2024/05/19 05:31

redis中的adlist是一个简单的无环双向链表,主要逻辑在这两个文件中实现:

  • adlist.h
  • adlist.c

结构也很简单,数据结构中最基本的结构。
这里写图片描述
添加节点代码:

if (after) {    node->prev = old_node;    node->next = old_node->next;    if (list->tail == old_node) {        list->tail = node;   }} else {   node->next = old_node;   node->prev = old_node->prev;   if (list->head == old_node) {       list->head = node;   }}

after控制是在old_node前面添加还是在后面添加。
adlist中实现了一个简单的迭代器:

typedef struct listIter {    //指向迭代方向的下一个节点    listNode *next;    //迭代节点    int direction;} listIter;

迭代器的一些方法:

//创建一个迭代器listIter *listGetIterator(list *list, int direction);//返回迭代器指向的节点并加一listNode *listNext(listIter *iter);void listReleaseIterator(listIter *iter);//将迭代器指针指向头void listRewind(list *list, listIter *li);//将迭代器指针指向尾巴void listRewindTail(list *list, listIter *li);

这样可以以如下代码来遍历整个链表:

listIter iter;listNode *node;listRewind(list, &iter);while((node = listNext(&iter)) != NULL) {    ......}

因为链表结构是无环的,所以只需要判断prev或者next是不是NULL就知道有没有到两端,缺点是没法直接在中间某个节点重新遍历整个链表。
链表结构提供了dup方法用于对每个节点进行拷贝。如果用户没有提供这个方法,那就进行浅拷贝复制指针,否则进行用户自定义拷贝。

list *listDup(list *orig){    list *copy;    listIter iter;    listNode *node;    if ((copy = listCreate()) == NULL)        return NULL;    //复制三个辅助函数    copy->dup = orig->dup;    copy->free = orig->free;    copy->match = orig->match;    listRewind(orig, &iter);    //遍历链表    while((node = listNext(&iter)) != NULL) {        void *value;        if (copy->dup) {            value = copy->dup(node->value);            if (value == NULL) {                listRelease(copy);                return NULL;            }        } else            value = node->value;        if (listAddNodeTail(copy, value) == NULL) {            listRelease(copy);            return NULL;        }    }    return copy;}
原创粉丝点击