Redisのソースコード解析(9) - Redisのダブルリンクリストの実装

adlist.h

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 int len;
    listIter iter;
} list;

adlist.c

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;
}
void listRelease(list *list)
{
    unsigned int 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;
    }
    zfree(list);
}

/*
 * 从头结点增加元素,即采用的是头插入法
 * 发生错误时将返回NULL
 */

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


/*
 * 采用尾插入法向链表中增加元素 
 * value是向链表中增加的值
 * 如果增加失败的话会返回空指针
 */

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

void listDelNode(list *list, listNode *node)
{
    if (node->prev)//判断删除节点是不是第一个节点
        node->prev->next = node->next;
    else
        list->head = node->next;
    if (node->next)//删除尾结点时的特殊处理情况
        node->next->prev = node->prev;
    else
        list->tail = node->prev;
    //如果链表结构中定义了结点释放函数,则调用注册的函数
    if (list->free) list->free(node->value);
    zfree(node);
    list->len--;
}

 /*
  * 链表的复制函数
  * 复制成功后,返回复制链表的头节点
  */

list *listDup(list *orig)
{
    list *copy;//复制链表的头指针
    listIter *iter;
    listNode *node;
    
    //创建链表的头节点
    if ((copy = listCreate()) == NULL)
        return NULL;
    //设置链表的复制函数
    copy->dup = orig->dup;
    //设置链表的释放函数
    copy->free = orig->free;
    //设置链表的匹配函数
    copy->match = orig->match;
    //获取链表的迭代器
    iter = listGetIterator(orig, AL_START_HEAD);
    //开始遍历链表,并复制链表中的元素值
    while((node = listNext(iter)) != NULL) {
        void *value;

        if (copy->dup) {
            value = copy->dup(node->value);
            if (value == NULL) {//复制失败时的情况
                listRelease(copy);//将复制一半的链表释放掉
                listReleaseIterator(iter);//释放链表的迭代器
                return NULL;
            }
        } else//这样会产生弱拷贝
            value = node->value;
        //将该值采用尾结点的方式进行插入
        if (listAddNodeTail(copy, value) == NULL) {
            //插入失败的情况下进行资源的回收
            listRelease(copy);
            listReleaseIterator(iter);
            return NULL;
        }
    }
    //复制完成后将迭代器所占用的内存空间释放掉
    listReleaseIterator(iter);
    return copy;
}

listNode *listSearchKey(list *list, void *key)
{
    listIter *iter;
    listNode *node;

    iter = listGetIterator(list, AL_START_HEAD);
    while((node = listNext(iter)) != NULL) {
        if (list->match) {//如果给链表设置了匹配函数的话,采用链表自身的匹配函数
            if (list->match(node->value, key)) {//如果匹配成功的话
                listReleaseIterator(iter);//释放迭代器所占用的内存空间
                return node;//返回链表当前的结点
            }
        } else {//如果未设置match函数的话
            if (key == node->value) {//直接比较指针里的地址
                listReleaseIterator(iter);//释放迭代器所占用的内存空间
                return node;//返回链表当前的结点
            }
        }
    }
    listReleaseIterator(iter);//释放迭代器所占用的内存空间
    return NULL;
}

/*
 * 返回指定索引位置的元素
 * index表示索引位置,从0开始
 * 如果index超了链表的长度NULL将返回
 * 负数表示从尾开始算起,即倒数
 */

listNode *listIndex(list *list, int index) {
    listNode *n;
    //-1表示尾节点 
    //-2表示的是尾节点的下一个节点
    if (index < 0) {
        index = (-index)-1;
        n = list->tail;
        while(index-- && n) n = n->prev;
    } else {
        //从头开始进行遍历时0指向head
        //1指向头节点的下一个元素
        n = list->head;
        while(index-- && n) n = n->next;
    }
    //返回索引位置的节点
    return n;
}
公開された257元の記事 ウォンの賞賛223 ビュー320 000 +

おすすめ

転載: blog.csdn.net/csdn_kou/article/details/103049633