zoukankan      html  css  js  c++  java
  • redis源码笔记-adlist

    adlist是redis自己是实现的一个通用的双向链表。

    ------------------------------------------------adlist.h---------------------------------------------------

    #ifndef __ADLIST_H__
    #define __ADLIST_H__
    
    /* Node, List, and Iterator are the only data structures used currently. */
    
    typedef struct listNode {
    struct listNode *prev;
    struct listNode *next;
    void *value;
    } listNode;        双向链表,存的结构是一个指针void*
    
    typedef struct listIter {
    listNode *next;
    int direction;
    } listIter;          迭代器,可以向前遍历,也可以向后遍历;
    
    typedef struct list {
    listNode *head;
    listNode *tail;
    void *(*dup)(void *ptr);
    void (*free)(void *ptr);
    int (*match)(void *ptr, void *key);
    unsigned int len;
    } list;                链表本身的结构,头、尾指针,同时一个函数指针dup用于在复制链表(list or listNode?)调用,一个函数指针free在释放链表时调用,一个函数指针match用来作匹配时调用,以及一个记录链表长度的字段;注意三个函数指针是list的成员,也就是被所有list node共用,因此listNode应该具有共性。
    
    /* 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))   set三个函数指针的方法
    
    #define listGetDupMethod(l) ((l)->dup)
    #define listGetFree(l) ((l)->free)
    #define listGetMatchMethod(l) ((l)->match)       get三个函数指针的方法
    
    /* Prototypes */
    list *listCreate(void);            创建链表
    void listRelease(list *list);      释放链表
    list *listAddNodeHead(list *list, void *value);       在表头加一个结点
    list *listAddNodeTail(list *list, void *value);         在表尾加一个结点
    list *listInsertNode(list *list, listNode *old_node, void *value, int after);
    void listDelNode(list *list, listNode *node);
    listIter *listGetIterator(list *list, int direction);
    listNode *listNext(listIter *iter);
    void listReleaseIterator(listIter *iter);
    list *listDup(list *orig);
    listNode *listSearchKey(list *list, void *key);
    listNode *listIndex(list *list, int index);
    void listRewind(list *list, listIter *li);
    void listRewindTail(list *list, listIter *li);
    
    /* Directions for iterators */
    #define AL_START_HEAD 0         
    #define AL_START_TAIL 1          定义迭代器方向
    
    #endif /* __ADLIST_H__ */

    ------------------------------------------------adlist.c---------------------------------------------------

      1 #include <stdlib.h>
      2 #include "adlist.h"
      3 #include "zmalloc.h"     //redis对内存分配库函数的一个封装,用于stat目的
      4 
      5 /* Create a new list. The created list can be freed with
      6  * AlFreeList(), but private value of every node need to be freed
      7  * by the user before to call AlFreeList().
      8  *
      9  * On error, NULL is returned. Otherwise the pointer to the new list. */
     10 list *listCreate(void)
     11 {
     12     struct list *list;
     13 
     14     if ((list = zmalloc(sizeof(*list))) == NULL)
     15         return NULL;
     16     list->head = list->tail = NULL;
     17     list->len = 0;
     18     list->dup = NULL;
     19     list->free = NULL;
     20     list->match = NULL;
     21     return list;
     22 }    //这个函数创建的list是个裸的list,三个函数指针需要自行调用set赋值
     23 
     24 /* Free the whole list.
     25  *
     26  * This function can't fail. */
     27 void listRelease(list *list)
     28 {
     29     unsigned int len;
     30     listNode *current, *next;
     31 
     32     current = list->head;
     33     len = list->len;
     34     while(len--) {
     35         next = current->next;
     36         if (list->free) list->free(current->value);      //
     37         zfree(current);
     38         current = next;
     39     }
     40     zfree(list);
     41 }       //先用free释放listNode中保存的元素,然后释放结点,最后释放链表本身。在链表操作中,注意在释放当前结点时,需要保存后续结点的值
     42 
     43 /* Add a new node to the list, to head, contaning the specified 'value'
     44  * pointer as value.
     45  *
     46  * On error, NULL is returned and no operation is performed (i.e. the
     47  * list remains unaltered).
     48  * On success the 'list' pointer you pass to the function is returned. */
     49 list *listAddNodeHead(list *list, void *value)
     50 {
     51     listNode *node;
     52 
     53     if ((node = zmalloc(sizeof(*node))) == NULL)
     54         return NULL;
     55     node->value = value;
     56     if (list->len == 0) {
     57         list->head = list->tail = node;
     58         node->prev = node->next = NULL;
     59     } else {
     60         node->prev = NULL;
     61         node->next = list->head;
     62         list->head->prev = node;
     63         list->head = node;
     64     }
     65     list->len++;
     66     return list;
     67 }
     68 
     69 /* Add a new node to the list, to tail, contaning the specified 'value'
     70  * pointer as value.
     71  *
     72  * On error, NULL is returned and no operation is performed (i.e. the
     73  * list remains unaltered).
     74  * On success the 'list' pointer you pass to the function is returned. */
     75 list *listAddNodeTail(list *list, void *value)
     76 {
     77     listNode *node;
     78 
     79     if ((node = zmalloc(sizeof(*node))) == NULL)
     80         return NULL;
     81     node->value = value;
     82     if (list->len == 0) {
     83         list->head = list->tail = node;
     84         node->prev = node->next = NULL;
     85     } else {
     86         node->prev = list->tail;
     87         node->next = NULL;
     88         list->tail->next = node;
     89         list->tail = node;
     90     }
     91     list->len++;
     92     return list;
     93 }
     94 
     95 list *listInsertNode(list *list, listNode *old_node, void *value, int after) {
     96     listNode *node;
     97 
     98     if ((node = zmalloc(sizeof(*node))) == NULL)
     99         return NULL;
    100     node->value = value;
    101     if (after) {
    102         node->prev = old_node;
    103         node->next = old_node->next;
    104         if (list->tail == old_node) {
    105             list->tail = node;
    106         }
    107     } else {
    108         node->next = old_node;
    109         node->prev = old_node->prev;
    110         if (list->head == old_node) {
    111             list->head = node;
    112         }
    113     }
    114     if (node->prev != NULL) {
    115         node->prev->next = node;
    116     }
    117     if (node->next != NULL) {
    118         node->next->prev = node;
    119     }
    120     list->len++;
    121     return list;
    122 }
    123 
    124 /* Remove the specified node from the specified list.
    125  * It's up to the caller to free the private value of the node.
    126  *
    127  * This function can't fail. */
    128 void listDelNode(list *list, listNode *node)
    129 {
    130     if (node->prev)
    131         node->prev->next = node->next;
    132     else
    133         list->head = node->next;
    134     if (node->next)
    135         node->next->prev = node->prev;
    136     else
    137         list->tail = node->prev;
    138     if (list->free) list->free(node->value);
    139     zfree(node);
    140     list->len--;
    141 }
    142 
    143 /* Returns a list iterator 'iter'. After the initialization every
    144  * call to listNext() will return the next element of the list.
    145  *
    146  * This function can't fail. */
    147 listIter *listGetIterator(list *list, int direction)
    148 {
    149     listIter *iter;
    150     
    151     if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL;
    152     if (direction == AL_START_HEAD)
    153         iter->next = list->head;
    154     else
    155         iter->next = list->tail;
    156     iter->direction = direction;
    157     return iter;
    158 }
    159 
    160 /* Release the iterator memory */
    161 void listReleaseIterator(listIter *iter) {
    162     zfree(iter);
    163 }
    164 
    165 /* Create an iterator in the list private iterator structure */
    166 void listRewind(list *list, listIter *li) {
    167     li->next = list->head;
    168     li->direction = AL_START_HEAD;
    169 }
    170 
    171 void listRewindTail(list *list, listIter *li) {
    172     li->next = list->tail;
    173     li->direction = AL_START_TAIL;
    174 }
    175 
    176 /* Return the next element of an iterator.
    177  * It's valid to remove the currently returned element using
    178  * listDelNode(), but not to remove other elements.
    179  *
    180  * The function returns a pointer to the next element of the list,
    181  * or NULL if there are no more elements, so the classical usage patter
    182  * is:
    183  *
    184  * iter = listGetIterator(list,<direction>);
    185  * while ((node = listNext(iter)) != NULL) {
    186  *     doSomethingWith(listNodeValue(node));
    187  * }
    188  *
    189  * */
    190 listNode *listNext(listIter *iter)
    191 {
    192     listNode *current = iter->next;
    193 
    194     if (current != NULL) {
    195         if (iter->direction == AL_START_HEAD)
    196             iter->next = current->next;
    197         else
    198             iter->next = current->prev;
    199     }
    200     return current;
    201 }       //注意这个函数,如果对返回值作delete操作,iter并未失效
    202 
    203 /* Duplicate the whole list. On out of memory NULL is returned.
    204  * On success a copy of the original list is returned.
    205  *
    206  * The 'Dup' method set with listSetDupMethod() function is used
    207  * to copy the node value. Otherwise the same pointer value of
    208  * the original node is used as value of the copied node.
    209  *
    210  * The original list both on success or error is never modified. */
    211 list *listDup(list *orig)
    212 {
    213     list *copy;
    214     listIter *iter;
    215     listNode *node;
    216 
    217     if ((copy = listCreate()) == NULL)
    218         return NULL;
    219     copy->dup = orig->dup;
    220     copy->free = orig->free;
    221     copy->match = orig->match;
    222     iter = listGetIterator(orig, AL_START_HEAD);
    223     while((node = listNext(iter)) != NULL) {
    224         void *value;
    225 
    226         if (copy->dup) {
    227             value = copy->dup(node->value);
    228             if (value == NULL) {
    229                 listRelease(copy);
    230                 listReleaseIterator(iter);
    231                 return NULL;
    232             }
    233         } else
    234             value = node->value;
    235         if (listAddNodeTail(copy, value) == NULL) {
    236             listRelease(copy);       //这里疑似有内存泄露,如果copy->dup被指定,并为value成功分配了内存,但addNodeTail的时候失败了,这块内存就没人管了。
    237             listReleaseIterator(iter);
    238             return NULL; 
    239         }
    240     }
    241     listReleaseIterator(iter);
    242     return copy;
    243 }  //如果没有指定dup函数则是个浅拷贝,否则是个深拷贝。
    244 
    245 /* Search the list for a node matching a given key.
    246  * The match is performed using the 'match' method
    247  * set with listSetMatchMethod(). If no 'match' method
    248  * is set, the 'value' pointer of every node is directly
    249  * compared with the 'key' pointer.
    250  *
    251  * On success the first matching node pointer is returned
    252  * (search starts from head). If no matching node exists
    253  * NULL is returned. */
    254 listNode *listSearchKey(list *list, void *key)
    255 {
    256     listIter *iter;
    257     listNode *node;
    258 
    259     iter = listGetIterator(list, AL_START_HEAD);
    260     while((node = listNext(iter)) != NULL) {
    261         if (list->match) {
    262             if (list->match(node->value, key)) {
    263                 listReleaseIterator(iter);
    264                 return node;
    265             }
    266         } else {
    267             if (key == node->value) {
    268                 listReleaseIterator(iter);
    269                 return node;
    270             }
    271         }
    272     }
    273     listReleaseIterator(iter);
    274     return NULL;
    275 } //O(n)的复杂度,n是链表长度
    276 
    277 /* Return the element at the specified zero-based index
    278  * where 0 is the head, 1 is the element next to head
    279  * and so on. Negative integers are used in order to count
    280  * from the tail, -1 is the last element, -2 the penultimante
    281  * and so on. If the index is out of range NULL is returned. */
    282 listNode *listIndex(list *list, int index) {
    283     listNode *n;
    284 
    285     if (index < 0) {
    286         index = (-index)-1; //注意从后边往前数时index的处理
    287         n = list->tail;
    288         while(index-- && n) n = n->prev;
    289     } else {
    290         n = list->head;
    291         while(index-- && n) n = n->next;
    292     }
    293     return n;
    294 }
  • 相关阅读:
    数据库更改自增和主键
    修改MySQL的默认数据存储引擎
    tomcat密码的坑
    通过System.getProperties()获取系统参数
    Java语言开发的,直接解压即可使用软件
    一个javascript面试题
    为什么学习差
    IDEA设置
    java关键字
    IDEA快捷键
  • 原文地址:https://www.cnblogs.com/liuhao/p/2495196.html
Copyright © 2011-2022 走看看