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 }
posted @ 2012-05-10 23:24  刘浩de技术博客  阅读(2001)  评论(0编辑  收藏  举报