// 调用hash生成函数,生成key对应的hash值
#define dictHashKey(d, key) (d)->type->hashFunction(key)
// 比较key1和key2是否相等,相等返回真
// 如果有提供key值比较的函数就调用这个函数,没有的话就直接比较key
#define dictCompareKeys(d, key1, key2) \
(((d)->type->keyCompare) ? \
(d)->type->keyCompare((d)->privdata, key1, key2) : \
(key1) == (key2))
// 目的是为了设置entry的key值
// 如果提供了keyDup函数就调用这个函数
// 没有的话key直接赋值
#define dictSetKey(d, entry, _key_) do { \
if ((d)->type->keyDup) \
entry->key = (d)->type->keyDup((d)->privdata, _key_); \
else \
entry->key = (_key_); \
} while(0)
// 目的是为了设置entry的val值
// 如果提供了valDup函数就调用这个函数
// 没有的话val直接赋值
#define dictSetVal(d, entry, _val_) do { \
if ((d)->type->valDup) \
entry->v.val = (d)->type->valDup((d)->privdata, _val_); \
else \
entry->v.val = (_val_); \
} while(0)
// 找到第一个大于size的数并且这个数字是2的幂
static unsigned long _dictNextPower(unsigned long size)
{
unsigned long i = DICT_HT_INITIAL_SIZE;
// 最大不能大于LONG_MAX
if (size >= LONG_MAX) return LONG_MAX;
while(1) {
if (i >= size)
return i;
i *= 2; // 2的幂
}
}
// 判断是否需要拓展hash table
// 注意返回的结果不是需不需要拓展,而是如果需要拓展就会直接拓展,返回值由dictExpand决定
// 不需要拓展则返回DICT_OK
static int _dictExpandIfNeeded(dict *d)
{
/* Incremental rehashing already in progress. Return. */
if (dictIsRehashing(d)) return DICT_OK;
/* If the hash table is empty expand it to the initial size. */
if (d->ht[0].size == 0) return dictExpand(d, DICT_HT_INITIAL_SIZE);
/* If we reached the 1:1 ratio, and we are allowed to resize the hash
* table (global setting) or we should avoid it but the ratio between
* elements/buckets is over the "safe" threshold, we resize doubling
* the number of buckets. */
if (d->ht[0].used >= d->ht[0].size &&
(dict_can_resize ||
d->ht[0].used/d->ht[0].size > dict_force_resize_ratio))
{
return dictExpand(d, d->ht[0].used*2);
}
return DICT_OK;
}
// 添加key-val到d这个字典中
/* Add an element to the target hash table */
int dictAdd(dict *d, void *key, void *val)
{
dictEntry *entry = dictAddRaw(d,key);
if (!entry) return DICT_ERR;
// 设置value值
dictSetVal(d, entry, val);
return DICT_OK;
}
dictEntry *dictAddRaw(dict *d, void *key)
{
int index;
dictEntry *entry;
dictht *ht;
if (dictIsRehashing(d)) _dictRehashStep(d);
/* Get the index of the new element, or -1 if
* the element already exists. */
if ((index = _dictKeyIndex(d, key)) == -1)
return NULL;
/* Allocate the memory and store the new entry */
// 如果正在rehash的话,直接返回ht[1]
ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0];
entry = zmalloc(sizeof(*entry));
entry->next = ht->table[index];// 头插法
ht->table[index] = entry; // 头插法
ht->used++; // 元素数加一
/* Set the hash entry fields. */
dictSetKey(d, entry, key);
return entry;
}
// 返回将来存储的索引位置
static int _dictKeyIndex(dict *d, const void *key)
{
unsigned int h, idx, table;
dictEntry *he;
/* Expand the hash table if needed */
if (_dictExpandIfNeeded(d) == DICT_ERR)
return -1;
/* Compute the key hash value */
// 计算hash值
h = dictHashKey(d, key);
for (table = 0; table <= 1; table++) {
idx = h & d->ht[table].sizemask;
/* Search if this slot does not already contain the given key */
he = d->ht[table].table[idx];
while(he) {
// 这一步防止同一链表中出现key值相同的情况,同一链表是hash值相同的key-val键值对
if (dictCompareKeys(d, key, he->key))
return -1;
he = he->next;
}
// 没有正在进行rehash的话直接结束
if (!dictIsRehashing(d)) break;
}
// 返回这个key对应的索引位置
return idx;
}
// 在字典中查找key对应的dictEntry
// 返回NULL,说明没找到
dictEntry *dictFind(dict *d, const void *key)
{
dictEntry *he;
unsigned int h, idx, table;
if (d->ht[0].size == 0) return NULL; /* We don't have a table at all */
if (dictIsRehashing(d)) _dictRehashStep(d);
// 计算hash值
h = dictHashKey(d, key);
for (table = 0; table <= 1; table++) {
// 找到对应的索引值
idx = h & d->ht[table].sizemask;
// 找到对应的链表
he = d->ht[table].table[idx];
while(he) {
// 遍历链表,并且比较每个元素的key,如果key值相等就返回这个dictEntry
if (dictCompareKeys(d, key, he->key))
return he;
he = he->next;
}
// 如果没有在rehash直接返回
if (!dictIsRehashing(d)) return NULL;
}
return NULL;
}
// 和dictAdd不同的是,如果原来的键值对不存在那么直接调用dictAdd插入
// 如果存在的话就替换他们
int dictReplace(dict *d, void *key, void *val)
{
dictEntry *entry, auxentry;
/* Try to add the element. If the key
* does not exists dictAdd will suceed. */
// 键值对原来就不存在,直接插入
if (dictAdd(d, key, val) == DICT_OK)
return 1;
/* It already exists, get the entry */
// 键值对存在
entry = dictFind(d, key);
/* Set the new value and free the old one. Note that it is important
* to do that in this order, as the value may just be exactly the same
* as the previous one. In this context, think to reference counting,
* you want to increment (set), and then decrement (free), and not the
* reverse. */
auxentry = *entry; // 这里可以解引用是因为上面已经确定了键值对存在,那么返回值一定不是NULL
dictSetVal(d, entry, val); // 修改对应的value值
dictFreeVal(d, &auxentry); // 释放原来的
return 0;
}
// 返回dictEntry中的key值
#define dictGetKey(he) ((he)->key)
// 返回dictEntry中的value值
#define dictGetVal(he) ((he)->v.val)
// 返回key对应的value值
void *dictFetchValue(dict *d, const void *key) {
dictEntry *he;
he = dictFind(d,key);
return he ? dictGetVal(he) : NULL;
}
// 先看到这里,后面用到啥在补充