redis6.0源码双端链表

在redis中列表键,发布和订阅、慢查询、监视器等都用到了链表,Redis服务器本身还是用链表来保存多个客户端的状态信息,以及使用链表来构建客户端输出缓冲区。

链表节点adlist.h/listNode

typedef struct listNode {
    struct listNode *prev;//前置节点
    struct listNode *next;//后置节点
    void *value;//节点值
} listNode;
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 *listCreate(void)
{
    struct list *list;
	//分配内存
    if ((list = zmalloc(sizeof(*list))) == NULL)
        return NULL;
    //初始化属性
    list->head = list->tail = NULL;
    list->len = 0;
    list->dup = NULL;
    list->free = NULL;
    list->match = NULL;
    return list;
}

链表头部插入新节点

list *listAddNodeHead(list *list, void *value)
{
    listNode *node;

    if ((node = zmalloc(sizeof(*node))) == NULL)
        return NULL;
    node->value = value;
    if (list->len == 0) {
        list->head = list->tail = node;
        node->prev = node->next = NULL;
    } else {
        node->prev = NULL;
        node->next = list->head;
        list->head->prev = node;
        list->head = node;
    }
    list->len++;
    return list;
}

链表尾部插入新节点

list *listAddNodeTail(list *list, void *value)
{
    listNode *node;

    if ((node = zmalloc(sizeof(*node))) == NULL)
        return NULL;
    node->value = value;
    if (list->len == 0) {
        list->head = list->tail = node;
        node->prev = node->next = NULL;
    } else {
        node->prev = list->tail;
        node->next = NULL;
        list->tail->next = node;
        list->tail = node;
    }
    list->len++;
    return 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 listGetFreeMethod(l) ((l)->free)
#define listGetMatchMethod(l) ((l)->match)

迭代器

typedef struct listIter {
    listNode *next;
    int direction;
} listIter;
  • listNode为具体某个节点信息
  • direction遍历方向 AL_START_HEAD为由头部向尾部遍历 AL_START_TAIL为由尾部向头部遍历

根据链表得到迭代器

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;
}

释放迭代器

void listReleaseIterator(listIter *iter) {
    zfree(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;
}

查询链表中和key匹配的节点

listNode *listSearchKey(list *list, void *key)
{
    listIter iter;
    listNode *node;
	//生成由头部->尾部的迭代器
    listRewind(list, &iter);
    //迭代器开始遍历每个节点
    while((node = listNext(&iter)) != NULL) {
        if (list->match) {
            if (list->match(node->value, key)) {
                return node;
            }
        } else {
            if (key == node->value) {
                return node;
            }
        }
    }
    return NULL;
}

更多讲解,欢迎关注我的github:
go成神之路

你可能感兴趣的:(redis)