redis源码分析三--双向链表adlist实现

1、adlist的结构

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中listNode的个数
} list;
typedef struct listIter {
    listNode *next;   //指向listNode
    int direction;   //接下来的方向,可以朝向head,也可以朝向tail
} listIter;

adlist中的主要的结构如下
redis源码分析三--双向链表adlist实现_第1张图片

2、 adlist主要函数解释

//复制整一个链表
list *listDup(list *orig)
{
    list *copy;
    listIter iter;
    listNode *node;

    if ((copy = listCreate()) == NULL)
        return NULL;
    //先将原来的函数复制到copy上
    copy->dup = orig->dup;
    copy->free = orig->free;
    copy->match = orig->match;
    //将listIter类型的iter和list类型的orig建立联系,并且iter遍历链表方向是从头向尾部遍历
    listRewind(orig, &iter);
    //如果还有下一个listNode,则继续
    while((node = listNext(&iter)) != NULL) {
        void *value;
		//如果有定义了自己的dup函数,则使用自己的,如果没有,则仅仅复制value值
        if (copy->dup) {
            value = copy->dup(node->value);
            if (value == NULL) {
                listRelease(copy);
                return NULL;
            }
        } else
            value = node->value;
        //将value值的listNode添加到copy链表上
        if (listAddNodeTail(copy, value) == NULL) {
            listRelease(copy);
            return NULL;
        }
    }
    return copy;
}
//获取一个关联在list链表上的listIter,方向为direction
listIter *listGetIterator(list *list, int direction)
{
    listIter *iter;

    if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL;
    //如果方向是从头到尾的方向,则iter的next首先指向head
    if (direction == AL_START_HEAD)
        iter->next = list->head;
    //如果方向是从尾到头的方向,则iter的next首先指向tail
    else
        iter->next = list->tail;
    iter->direction = direction;
    return iter;
}
list *listInsertNode(list *list, listNode *old_node, void *value, int after) {
    listNode *node;

    if ((node = zmalloc(sizeof(*node))) == NULL)
        return NULL;
    node->value = value;
    //after标志表示添加的节点时候在old_node节点的后面还是前面
    if (after) {
    	//对node节点的prev和next指针赋值
        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;
        }
    }
    //node节点的前置节点的next和node节点的后置节点的prev进行赋值
    if (node->prev != NULL) {
        node->prev->next = node;
    }
    if (node->next != NULL) {
        node->next->prev = node;
    }
    //增加list的长度
    list->len++;
    return list;
}

3、adlist函数介绍

函数 参数 释义
listAddNodeHead list *list, void *value 添加节点到头部
listAddNodeTail list *list, void *value 添加节点到尾部
listCreate void 创建list链表,初始化参数为NULL,长度为0
listDelNode list *list, listNode *node 删除一个节点,需要注意有两处地方删除,在链表中删除用list->free(node->value),删除这个节点用zfree(node)
listEmpty list *list 移除这个链表中所有数据
listIndex list *list, long index 返回链表中序号为index的节点,如果index为正数,则从头开始,如果index为负数,则从尾部开始计数
listNext listIter *iter 返回当点节点的下一个节点,但是具体是上一个节点还是下一个节点需要看listIter中的方向
listRewind list *list, listIter *li 将listIter和list建立联系,同时说明方向是从头到尾。listRewindTail则方向时候从尾到头
listRotate list *list 将list链表中的最后一个节点移动到最前面
listSearchKey list *list, void *key 利用match函数来查找并返回符合key的node

你可能感兴趣的:(redis)