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 }