1 dictCreate
1.1 方法说明
??创建一个新的 hash table
1.2 方法源码
dict *dictCreate(dictType *type,
void *privDataPtr)
{
dict *d = zmalloc(sizeof(*d));
_dictInit(d,type,privDataPtr);
return d;
}
1.3 相关方法
1.3.1 _dictInit
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;
}
1.3.2 _dictReset
static void _dictReset(dictht *ht)
{
ht->table = NULL;
ht->size = 0;
ht->sizemask = 0;
ht->used = 0;
}
1.4 代码理解
- 先申明一个字典结构体,并分配相应内存。
- 调用 _dictInit 初始化字典。
- 调用 _dictReset 初始化字典中两个哈希表。
- 将哈希表中几个属性字段都设置为初始值。
2 dictAdd
2.1 方法说明
??增加一个哈希节点到哈希表中。
2.2 方法源码
int dictAdd(dict *d, void *key, void *val)
{
dictEntry *entry = dictAddRaw(d,key);
if (!entry) return DICT_ERR;
dictSetVal(d, entry, val);
return DICT_OK;
}
2.3 相关代码
2.3.1 dictAddRaw
dictEntry *dictAddRaw(dict *d, void *key)
{
int index;
dictEntry *entry;
dictht *ht;
if (dictIsRehashing(d)) _dictRehashStep(d);
if ((index = _dictKeyIndex(d, key)) == -1)
return NULL;
ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0];
entry = zmalloc(sizeof(*entry));
entry->next = ht->table[index];
ht->table[index] = entry;
ht->used++;
dictSetKey(d, entry, key);
return entry;
}
2.3.2 _dictKeyIndex
static int _dictKeyIndex(dict *d, const void *key)
{
unsigned int h, idx, table;
dictEntry *he;
if (_dictExpandIfNeeded(d) == DICT_ERR)
return -1;
h = dictHashKey(d, key);
for (table = 0; table <= 1; table++) {
idx = h & d->ht[table].sizemask;
he = d->ht[table].table[idx];
while(he) {
if (dictCompareKeys(d, key, he->key))
return -1;
he = he->next;
}
if (!dictIsRehashing(d)) break;
}
return idx;
}
2.4 代码理解
- 调用 dictAddRaw 增加一个哈希节点
- 计算键的索引值,如果该值已经存在则返回错误
- 如果正在进行 rehash 的话,会向第二个哈希表中新增节点
- 调用宏定义方法 dictSetKey 设置哈希节点的键
- 调用宏定义方法 dictSetVal 设置哈希节点的值
3 学习总结
- 增加新的哈希节点的时候,如果节点已存在则会报错。
- 调用 dictHashKey 计算键的哈希值。
- 再用哈希值与字典掩码计算出索引位置。
- 遍历两个哈希表,判断键是否已存在。
- 如果字典正在 rehash 中的话,则新增的节点会加到第二个哈希表中。
- 如果字典正在 rehash 中的话, 则会进行一步的 rehash 的动作。
|