redis源码学习之adlist

参考《Redis 设计与实现》 (基于redis3.0.0) 作者:黄健宏
学习redis3.2.13

TOC

介绍

链表简单了解:

  • 链表是一种线性结构,由很多节点串联在一起,每个节点间由指针连接。
  • 每个节点含存储数据部分与指向下一个节点的部分。
  • 链表的节点可动态增减,增减头尾节点时间复杂度为O(1)。非常适合数据量预先难以知晓或变化频繁的情况。

注:增减头尾节点时间复杂度为O(1)的前提是,拥有头结点的同时拥有尾节点指针
C语言没有链表这种数据结构,redis造了属于它自己的链表

链表结构

节点定义

typedef struct listNode {
    //指向前一个节点
    struct listNode *prev;
    //指向后一个节点
    struct listNode *next;
    //指向存储的值
    void *value;
} listNode;

根据节点的结构可知redis中的链表为双向链表,取书中的例子如图:

管理结构定义

typedef struct list {
    //头节点指针
    listNode *head;
    //尾节点指针
    listNode *tail;
    //自定义dup函数指针,用于节点存储值的深拷贝
    void *(*dup)(void *ptr);
    //自定义free函数指针,用于节点存储值的释放
    void (*free)(void *ptr);
    //自定义match函数指针,用于检查节点存储值是否与key匹配
    int (*match)(void *ptr, void *key);
    //节点长度
    unsigned long len;
} list;

还是取书中的已有例子,redis链表结构直观描述如下:

节点中的数据域是void *类型,配合管理结构中的函数指针,这使得其支持任意数据的存储

迭代器

redis的list实现了自己的迭代器,list的遍历由迭代器的来提供,使遍历操作得以简化
迭代器结构定义如下

typedef struct listIter {
    //指向的节点
    listNode *next;
    //迭代方向
    int direction;
} listIter;
//迭代方向定义如下
#define AL_START_HEAD 0
#define AL_START_TAIL 1

迭代器的获取

//获取链表指定迭代方向的迭代器
listIter *listGetIterator(list *list, int direction)
{
    listIter *iter;

    if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL;
    if (direction == AL_START_HEAD)
        iter->next = list->head;
    else
        iter->next = list->tail;
    iter->direction = direction;
    return iter;
}

迭代器的游走方式

//获取迭代器所指对象并游走迭代器
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;
}

使用迭代器遍历

    ...
    #define listNodeValue(n) ((n)->value)
    ...
    listIter *iter = listGetIterator(list,<direction>);
    while ((node = listNext(iter)) != NULL) {
    //   doSomethingWith(listNodeValue(node));    
     }

后记

  • 通过void *类型存储数据,函数指针存储处理数据的对应方法,以回调的方式执行,可增加容器的灵活性
  • 使用迭代器可以简化遍历操作




posted @ 2020-12-04 22:42  無雙  阅读(126)  评论(0编辑  收藏  举报