Redis 2.8.9源码 - 双向链表操作函数头整理,并注释作用和参数说明(附测试方法和代码)

本文为作者原创,转载请注明出处:http://my.oschina.net/fuckphp/blog/269685

如果需要对函数进行测试可以在源代码(src/adlist.c)下面加入以下代码,然后在main中加入你的测试代码:

#ifdef ADLIST_TEST_MAIN
#include <stdio.h>

int main(void)
{
    printf("Hi\n");
    return 1;
}
#endif

并用以下命令进行编译,并执行 ./a.out:

gcc zmalloc.c adlist.c -D ADLIST_TEST_MAIN

文章底部附了一份我自己的测试代码(按上面办法加入编译即可 编译时候参数增加 sds.c):测试代码

链表相关的头注释:

/**
 * 获取链表长度
 * list l 链表结构
 * return 返回链表的len属性
 */
#define listLength(l) ((l)->len)


/**
 * 获取链表第一个节点
 * list l 链表结构
 * return 返回链表的head属性
 */
#define listFirst(l) ((l)->head)


/**
 * 获取链表最后一个节点
 * list l 链表结构
 * return 返回链表的tail属性
 */
#define listLast(l) ((l)->tail)


/**
 * 获取链表当前节点的上一个节点
 * listNode n 链表节点结构
 * return 返回链表节点的prev属性
 */
#define listPrevNode(n) ((n)->prev)


/**
 * 获取链表当前节点的下一个节点
 * listNode n 链表节点结构
 * return 返回链表节点的next属性
 */
#define listNextNode(n) ((n)->next)


/**
 * 获取链表当前节点的值
 * listNode n 链表节点结构
 * return 返回链表节点的value属性
 */
#define listNodeValue(n) ((n)->value)


/**
 * 设置复制链表时候的回调函数
 * list l 链表结构
 * void *(*dup)(void *ptr) m 回调函数
 * return void
 */
#define listSetDupMethod(l,m) ((l)->dup = (m))


/**
 * 设置释放链表时候的回调函数
 * list l 链表结构
 * void (*free)(void *ptr); m 回调函数
 * return void
 */
#define listSetFreeMethod(l,m) ((l)->free = (m))


/**
 * 设置比较链表节点时候的回调函数
 * list l 链表结构
 * int (*match)(void *ptr, void *key); m 回调函数
 * return void
 */
#define listSetMatchMethod(l,m) ((l)->match = (m))


/**
 * 获取复制链表时候的回调函数
 * list l 链表结构
 * return 复制函数的函数指针
 */
#define listGetDupMethod(l) ((l)->dup)


/**
 * 获取释放链表时候的回调函数
 * list l 链表结构
 * return 释放函数的函数指针
 */
#define listGetFree(l) ((l)->free)


/**
 * 获取比较链表时候的回调函数
 * list l 链表结构
 * return 比较函数的函数指针
 */
#define listGetMatchMethod(l) ((l)->match)


/**
 * 创建一个空的链表
 * return 返回空的list指针
 */
list *listCreate(void);


/**
 * 遍历并释放所有Node节点释放节点前如果设置了free函数,则先调用free函数来释放节点的值,用来避免内存泄露
 * list *list 需要释放的list结构
 * return void
 */
void listRelease(list *list);


/**
 * 根据 value 创建一个listNode节点,并将它加入到list链表的头部
 * list *list 增加节点的list链表
 * void *value listNode节点的值
 * return 返回被操作的链表
 */
list *listAddNodeHead(list *list, void *value);


/**
 * 根据 value 创建一个listNode节点,并将它加入到list链表的尾部
 * list *list 增加节点的list链表
 * void *value listNode节点的值
 * return 返回被操作的链表
 */
list *listAddNodeTail(list *list, void *value)


/**
 * 根据 value 创建一个listNode节点,并将它加入到list old_node 之后(如果after为1加old_node之后,为0加到old_node之前)
 * list *list 增加节点的list链表
 * listNode *old_node 增加在哪个节点的旁边
 * void *value listNode节点的值
 * int after 如果after为1加old_node之后,为0加到old_node之前
 * return 返回被操作的链表
 */
list *listInsertNode(list *list, listNode *old_node, void *value, int after);



/**
 * 将指定的节点node 在list中删除,并释放删除的node
 * list *list 删除节点的list链表
 * listNode *node 待删除的节点
 * return 返回被操作的链表
 */
void listDelNode(list *list, listNode *node);


/**
 * 复制一个list如果用户设置了dup函数,则会根据dup函数来复制每个节点的value
 * list *list 被复制的list
 * return 返回复制后的list
 */
list *listDup(list *orig);


/**
 * 从list中每个节点中查找key,如果用户定义了match则根据用户的match函数来决定是否匹配
 * list *list 被查找的list
 * void *key 用于跟list中每个节点的value进行比较
 * return 找到的节点,没找到返回NULL
 */
listNode *listSearchKey(list *list, void *key);


/**
 * 根据index查找对应的节点并返回
 * list *list 被查找的list
 * int index 索引号
 * return 返回对应的节点
 */
listNode *listIndex(list *list, long index);



/**
 * 将list尾部的节点移动到list的头部
 * list *list 被操作的list
 * return void
 */
void listRotate(list *list);


链表迭代器相关的函数投说明:

/**
 * 创建一个迭代器的结构,并将迭代器指针根据direction参数来指向链表的头部或者尾部
 * list *list 需要遍历的列表
 * int direction 方向 AL_START_HEAD / AL_START_TAIL
 * return 返回迭代器listIter指针
 */
listIter *listGetIterator(list *list, int direction);


/**
 * 释放一个迭代器的结构
 * listIter *iter 需要释放的迭代器结构
 * return void
 */
void listReleaseIterator(listIter *iter);


/**
 * 设置链表从头开始遍历(其实就是将遍历的游标指向头部)
 * list *list 需要设置的列表结构
 * listIter *li 需要设置的迭代器
 * return void
 */
void listRewind(list *list, listIter *li);


/**
 * 设置链表从尾开始遍历(其实就是将遍历的游标指向尾部)
 * list *list 需要设置的列表结构
 * listIter *li 需要更设置迭代器
 * return 返回迭代器listIter指针
 */
void listRewindTail(list *list, listIter *li);


/**
 * 根据迭代器的direction获取迭代器指向的下一个及诶单
 * listIter *li 用于遍历的迭代器接口
 * return 返回下一个节点
 */
listNode *listNext(listIter *iter);

测试代码:

#ifdef ADLIST_TEST_MAIN
#include <stdio.h>
#include "sds.h"

void *testDup(void *ptr)
{
    return sdsdup(ptr);
}
void testFree(void *ptr)
{
    sdsfree(ptr);
}
int testMatch(void *ptr, void *key)
{
    int n = 0;
    n = sdscmp(ptr, key) == 0 ? 1 : 0;
    printf("cmp: %s, %s, %d\n", ptr, key, n);
    return n;
}

int main(void)
{
    //设置用于测试的一些临时变量
    listNode *n;
    listIter *iter;
    sds str;
    //创建一个空的双端链表
    list *l = listCreate();
    //设置回调函数
    listSetDupMethod(l, testDup);
    listSetFreeMethod(l, testFree);
    listSetMatchMethod(l, testMatch);
    //将数据加入到链表尾端
    listAddNodeTail(l, sdsnewlen("Redis", 5));
    listAddNodeTail(l, sdsnewlen("PHP", 3));
    listAddNodeTail(l, sdsnewlen("MySQL", 5));
    listAddNodeTail(l, sdsnewlen("Hadoop", 6));
    listAddNodeTail(l, sdsnewlen("Strom", 5));
    printf("adlist length:%d\n\n", listLength(l));
    //查找名为Hadoop的节点
    str = sdsnewlen("Hadoop", 6);
    n = listSearchKey(l, str);
    sdsfree(str);
    if (n != NULL) {
        printf("Search Result:%s\n\n", listNodeValue(n));
    } else {
        printf("NO Result!!!\n\n");
    }
    //遍历并输出所有数据
    iter = listGetIterator(l, AL_START_HEAD);
    while ((n = listNext(iter))) {
        printf("Node Value: %s\n", listNodeValue(n));
    }
    printf("\n");
    //查找并删除索引为3的数据
    n = listIndex(l, 3);
    if (n) {
        printf("Index 3 Is:%s\n\n", listNodeValue(n));
        //删除索引为3的数据
        listDelNode(l, n);
        printf("Index 3 is Removed, adlist length:%d\n\n", listLength(l));
    } else {
        printf("Index 3 Is Not Exists!!!\n\n");
    }
    
    //将新的节点加入到索引为1的后面
    n = listIndex(l, 1);
    if (n) {
        listInsertNode(l, n, sdsnewlen("Python", 6), 1);
        //将新的节点加入到索引为1的前面
        listInsertNode(l, n, sdsnewlen("Nginx", 5), 0);
        printf("Add Python before Index 1, Add Nginx After Index 1, adlist length:%d\n", listLength(l));
        //遍历并输出所有数据
        iter = listGetIterator(l, AL_START_HEAD);
        while ((n = listNext(iter))) {
            printf("Node Value: %s\n", listNodeValue(n));
        }
        printf("\n");
    }
    
    listRelease(l);
    return 1;
}
#endif


你可能感兴趣的:(redis,链表,list,双向链表,redis源码)