日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

redis源码笔记-adlist

發(fā)布時(shí)間:2024/4/17 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redis源码笔记-adlist 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

adlist是redis自己是實(shí)現(xiàn)的一個(gè)通用的雙向鏈表。

------------------------------------------------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; 雙向鏈表,存的結(jié)構(gòu)是一個(gè)指針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; 鏈表本身的結(jié)構(gòu),頭、尾指針,同時(shí)一個(gè)函數(shù)指針dup用于在復(fù)制鏈表(list or listNode?)調(diào)用,一個(gè)函數(shù)指針free在釋放鏈表時(shí)調(diào)用,一個(gè)函數(shù)指針match用來(lái)作匹配時(shí)調(diào)用,以及一個(gè)記錄鏈表長(zhǎng)度的字段;注意三個(gè)函數(shù)指針是list的成員,也就是被所有l(wèi)ist node共用,因此listNode應(yīng)該具有共性。/* Functions implemented as macros */ #define listLength(l) ((l)->len) 鏈表長(zhǎng)度 #define listFirst(l) ((l)->head) 鏈表的第一個(gè)結(jié)點(diǎn) #define listLast(l) ((l)->tail) 鏈表的最后一個(gè)結(jié)點(diǎn) #define listPrevNode(n) ((n)->prev) 當(dāng)前結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn) #define listNextNode(n) ((n)->next) 當(dāng)前結(jié)點(diǎn)的后一個(gè)結(jié)點(diǎn) #define listNodeValue(n) ((n)->value) 當(dāng)前結(jié)點(diǎn)的值#define listSetDupMethod(l,m) ((l)->dup = (m)) #define listSetFreeMethod(l,m) ((l)->free = (m)) #define listSetMatchMethod(l,m) ((l)->match = (m)) set三個(gè)函數(shù)指針的方法#define listGetDupMethod(l) ((l)->dup) #define listGetFree(l) ((l)->free) #define listGetMatchMethod(l) ((l)->match) get三個(gè)函數(shù)指針的方法/* Prototypes */ list *listCreate(void); 創(chuàng)建鏈表 void listRelease(list *list); 釋放鏈表 list *listAddNodeHead(list *list, void *value); 在表頭加一個(gè)結(jié)點(diǎn) list *listAddNodeTail(list *list, void *value); 在表尾加一個(gè)結(jié)點(diǎn) 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對(duì)內(nèi)存分配庫(kù)函數(shù)的一個(gè)封裝,用于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 } //這個(gè)函數(shù)創(chuàng)建的list是個(gè)裸的list,三個(gè)函數(shù)指針需要自行調(diào)用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中保存的元素,然后釋放結(jié)點(diǎn),最后釋放鏈表本身。在鏈表操作中,注意在釋放當(dāng)前結(jié)點(diǎn)時(shí),需要保存后續(xù)結(jié)點(diǎn)的值 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 } //注意這個(gè)函數(shù),如果對(duì)返回值作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); //這里疑似有內(nèi)存泄露,如果copy->dup被指定,并為value成功分配了內(nèi)存,但addNodeTail的時(shí)候失敗了,這塊內(nèi)存就沒(méi)人管了。 237 listReleaseIterator(iter); 238 return NULL; 239 } 240 } 241 listReleaseIterator(iter); 242 return copy; 243 } //如果沒(méi)有指定dup函數(shù)則是個(gè)淺拷貝,否則是個(gè)深拷貝。 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)的復(fù)雜度,n是鏈表長(zhǎng)度 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; //注意從后邊往前數(shù)時(shí)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 }

轉(zhuǎn)載于:https://www.cnblogs.com/liuhao/archive/2012/05/10/2495196.html

總結(jié)

以上是生活随笔為你收集整理的redis源码笔记-adlist的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。