redis7.x源码分析:(2) adlist双向链表

链表是一种常用的数据结构(如果不了解,请先学习数据结构),由于c语言本身没有实现标准的链表库,所以redis自己实现了一个双向链表。

双向链表在redis内部的使用非常的多,几乎所有模块中都有用到。

下面看下它的结构定义:

cpp 复制代码
// 节点
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;

listNode中的value定义为void *,所以它可以被用来存储任意类型的数据。而对于不同的数据,在处理时可能需要用到不同的函数,因此在list中定义了3个函数指针,分别对应不同类型数据的复制、释放和对比功能。当对value进行处理时,如果设置了函数指针,就有可能会调用它们进行相应处理。

比如在清空函数中:

cpp 复制代码
void listEmpty(list *list)
{
    unsigned long len;
    listNode *current, *next;

    current = list->head;
    len = list->len;
    while(len--) {
        next = current->next;
        // 释放
        if (list->free) list->free(current->value);
        zfree(current);
        current = next;
    }
    list->head = list->tail = NULL;
    list->len = 0;
}

当 free 函数指针不为空时,会调用它释放value。而 dup 和 match 函数会分别在 listDup 和 listSearchKey 中使用。由于双向链表整体代码实现比较简单,因此其它代码也不作过多说明。

最后我们再简单看下迭代器:

cpp 复制代码
// 迭代器
typedef struct listIter {
    listNode *next;
    int direction;
} listIter;

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

它由一个节点指针和迭代方向组成

  • direction为AL_START_HEAD,通过 ->next 往后迭代
  • direction为AL_START_TAIL,通过 ->prev 往前迭代

迭代器的相关函数:

cpp 复制代码
// 创建迭代器
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);
相关推荐
CodeBlossom几秒前
Redis速通
数据库·redis·缓存
2401_837088509 分钟前
Redis的vim基本操作
linux·编辑器·vim
馨谙13 分钟前
标题:Linux 系统中的“保险库管理员”:深入浅出理解 /etc/shadow 文件
linux·运维·服务器
---学无止境---17 分钟前
Linux中zonelist分配策略初始化
linux
撬动未来的支点1 小时前
【Linux内核】Linux系统启动之旅
linux
乌萨奇也要立志学C++2 小时前
【Linux】基础IO(一)Linux 文件操作从入门到实践:系统调用、文件描述符、重定向,为自定义Shell添加重定向
linux·运维·chrome
麦麦麦造4 小时前
小小 Postgres,何以替代 Redis、MongoDB 甚至 ES?
redis·mongodb·elasticsearch·postgresql
liujing102329296 小时前
stm32大项目阶段20251015
linux
嵌入式郑工7 小时前
LINUX驱动开发: 设备和驱动是怎么匹配的?
linux·运维·服务器
郭式云源生法则9 小时前
归档及压缩、重定向与管道操作和综合使用,find精确查找、find处理查找结果、vim高级使用、vimdiff多文件使用
linux·运维·服务器