Redis源码:dict数据结构(实现)
2017-04-07 22:33
239 查看
高屋建瓴
本文分析的是src/dict.c文件。从结构上来说,可以分为:
1. 私有函数(以下划线开头的一般都是,一般都是一些辅助函数);
2. 公开API。
从功能来说,可以分为:
1. dict初始化、析构;
2. 元素操作:查找、删除、插入、替换/修改值、清空数据;
3. 遍历dict,迭代器相关(比如需要持久化哈希表的数据时就很有用);
4. 扩展哈希表(也就是增量扩展哈希表);
5. 哈希函数(这些需要数学知识才能懂,个人觉得开箱即用就好了);
6. 随机化函数……(目前不知道有什么用)。
读完之后,我个人觉得,重点是理解好incremental rehashing是怎么做的以及哈希表的基本操作,其它的都很容易了。
创建与销毁dict
先回顾一下dict的定义,这对理解初始化和析构有好处:typedef struct dict { dictType *type; void *privdata; dictht ht[2]; long rehashidx; /* rehashing not in progress if rehashidx == -1 */ int iterators; /* number of iterators currently running */ } dict;
可以看到,其中除了基础类型(long和int)之外,还有指针和一个dictht数组。一般指针初始化为NULL就好了,然后rehashidx的初始值应该是-1,iterators的初始值应该是0,然后我的一些想法写成了注释放在代码里。
关于创建和初始化,涉及到下面三个函数:
// 其实我觉得这个函数名应该改为_dicthtInit才对, // 因为既不是对dict修改(而是对dictht进行修改), // 也不是Reset操作(而是初始化操作) static void _dictReset(dictht *ht) { ht->table = NULL; ht->size = 0; ht->sizemask = 0; ht->used = 0; } /* Create a new hash table */ // 其实我到现在还不知道privdata是什么……待补充 dict *dictCreate(dictType *type, void *privDataPtr) { // 注意Redis对malloc封装了,这使得可以自己选择不同的malloc方案 dict *d = zmalloc(sizeof(*d)); _dictInit(d,type,privDataPtr); return d; } /* Initialize the hash table */ // 上面这行注释也有问题,其实是Initialize the dict…… // 机灵的朋友赶紧做pull request,说不定真的可以被accept // 还有很多地方的代码风格不统一,比如函数传参时多个参数之间只有逗号没有空格 int _dictInit(dict *d, dictType *type, void *privDataPtr) { _dictReset(&d->ht[0]); _dictReset(&d->ht[1]); d->type = type; d->privdata = privDataPtr; d->rehashidx = -1; d->iterators = 0; return DICT_OK; }
关于dict的销毁,涉及到下面两个函数,关键知识点是,如何释放动态创建的内容。
/* Destroy an entire dictionary */ // 噢...注释又错了,应该是Destroy an entire dict hash table int _dictClear(dict *d, dictht *ht, void(callback)(void *)) { unsigned long i; /* Free all the elements */ // 讲道理,ht->used > 0这个判断应该是已经够了的,i < ht->size还需要吗?(为了更安全?) for (i = 0; i < ht->size && ht->used > 0; i++) { dictEntry *he, *nextHe; if (callback && (i & 65535) == 0) callback(d->privdata); if ((he = ht->table[i]) == NULL) continue; // 释放一条链表 // 需要先保存下一个结点,因为当前这个结点在赋值之前会被free掉 while(he) { nextHe = he->next; dictFreeKey(d, he); dictFreeVal(d, he); zfree(he); ht->used--; he = nextHe; } } /* Free the table and the allocated cache structure */ zfree(ht->table); /* Re-initialize the table */ _dictReset(ht); return DICT_OK; /* never fails */ } /* Clear & Release the hash table */ // 值得注意的是,只有动态创建的数据需要自己释放 // 还有,它的编程风格,一下子有空格,一下子没有,but not big deal. void dictRelease(dict *d) { _dictClear(d,&d->ht[0],NULL); _dictClear(d,&d->ht[1],NULL); zfree(d); }
增量扩展
later……相关文章推荐
- 【Redis源码剖析】 - Redis内置数据结构之字典dict
- redis源码分析 dict字典的实现和内部应用
- Redis源码:dict数据结构(声明)
- 【Redis源码剖析】 - Redis内置数据结构之字典dict
- 结合redis设计与实现的redis源码学习-4-dict(字典)
- 【Redis源码剖析】 - Redis内置数据结构之字典dict
- redis 源码 dict.c 实现
- redis源码解析之dict数据结构
- Redis源码分析(三十四)--- redis.h服务端的实现分析(1)
- redis源码笔记-dict.c
- Redis源码学习3-基本数据结构之双向链表
- Redis源码分析(二十五)--- zmalloc内存分配实现
- redis的源码分析之不同编码类型的数据结构
- Redis的字典(dict)rehash过程源码解析
- redis dict.c源码分析
- BitSet数据结构以及jdk中实现源码分析
- Redis源码分析-内存数据结构intset
- 【redis源码分析】字典---dict
- redis源码笔记-dict.h
- redis源码解读之哈希接口————dict.h文件