redis雙向鏈表實(shí)現(xiàn)(3)

鏈表(list)是Redis中最基本的數(shù)據(jù)結(jié)構(gòu), 由adlist.h和adlist.c定義
事務(wù)模塊使用雙端鏈表依序保存輸入的命令; 服務(wù)器模塊使用雙端鏈表來(lái)保存多個(gè)客戶(hù)端; 訂閱/發(fā)送模塊使用雙端鏈表來(lái)保存訂閱模式的多個(gè)客戶(hù)端; 事件模塊使用雙端鏈表來(lái)保存時(shí)間事件(time event);

1.數(shù)據(jù)類(lèi)型

//節(jié)點(diǎn)
typedef struct listNode {
    struct listNode *prev;
    struct listNode *next;
    void *value;
} listNode;

//迭代對(duì)象
typedef struct listIter {
    listNode *next;
    int direction;
} listIter;

//鏈表
typedef struct list {
    listNode *head;
    listNode *tail;
    void *(*dup)(void *ptr);//復(fù)制(dup)
    void (*free)(void *ptr);//釋放(free)
    int (*match)(void *ptr, void *key);//匹配(match)
    unsigned long len;
} list;

2.基本操作

(1)復(fù)制釋放匹配函數(shù)手動(dòng)復(fù)制

#define listSetDupMethod(l,m) ((l)->dup = (m))
#define listSetFreeMethod(l,m) ((l)->free = (m))
#define listSetMatchMethod(l,m) ((l)->match = (m))

(2)迭代器

//獲得迭代器對(duì)象
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;
}

//釋放迭代器對(duì)象
/* Release the iterator memory */
void listReleaseIterator(listIter *iter) {
    zfree(iter);
}

/* Create an iterator in the list private iterator structure */
//重新指向鏈表頭
void listRewind(list *list, listIter *li) {
    li->next = list->head;
    li->direction = AL_START_HEAD;
}

//重新指向迭代器的尾部
void listRewindTail(list *list, listIter *li) {
    li->next = list->tail;
    li->direction = AL_START_TAIL;
}

/* Return the next element of an iterator.
 * It's valid to remove the currently returned element using
 * listDelNode(), but not to remove other elements.
 *
 * The function returns a pointer to the next element of the list,
 * or NULL if there are no more elements, so the classical usage patter
 * is:
 *
 * iter = listGetIterator(list,<direction>);
 * while ((node = listNext(iter)) != NULL) {
 *     doSomethingWith(listNodeValue(node));
 * }
 *
 * */
//?。。?!遍歷迭代器
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;
}

(3)基本操作

/創(chuàng)建list,分配內(nèi)存
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;
}

/* Free the whole list.
 *
 * This function can't fail. */
//釋放list
void listRelease(list *list)
{
    unsigned long len;
    listNode *current, *next;

    current = list->head;
    len = list->len;
    //先釋放節(jié)點(diǎn)內(nèi)存
    while(len--) {
        next = current->next;
        if (list->free) list->free(current->value);
        zfree(current);
        current = next;
    }
    //再釋放鏈表內(nèi)存
    zfree(list);
}

/* Add a new node to the list, to head, containing the specified 'value'
 * pointer as value.
 *
 * On error, NULL is returned and no operation is performed (i.e. the
 * list remains unaltered).
 * On success the 'list' pointer you pass to the function is returned. */
//在鏈表頭增加一個(gè)節(jié)點(diǎn)
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;
}
//復(fù)制雙向鏈表
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;
    //創(chuàng)建迭代器
    listRewind(orig, &iter);
    while((node = listNext(&iter)) != NULL) {
        void *value;

        if (copy->dup) {
            value = copy->dup(node->value);
            if (value == NULL) {
                listRelease(copy);
                return NULL;
            }
        } else
            value = node->value;
        if (listAddNodeTail(copy, value) == NULL) {
            listRelease(copy);
            return NULL;
        }
    }
    return copy;
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,525評(píng)論 19 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,828評(píng)論 25 709
  • 順豐快遞小哥被打這事說(shuō)起來(lái),挺令人火大。 網(wǎng)友拍攝的視頻顯示,打人的中年人在短短不到兩分鐘之內(nèi)連打了快遞小哥6個(gè)耳...
    鄰居知道閱讀 710評(píng)論 0 0
  • 如果要用一個(gè)詞語(yǔ)來(lái)形容成都,那么一定會(huì)是“悠閑”,如果給“悠閑”下一個(gè)定義,那便是“慢”。且行且慢,漸行漸緩,在緩...
    初棠閱讀 1,744評(píng)論 10 11

友情鏈接更多精彩內(nèi)容