ypedef struct dictEntry {
void *key;
union {
void *val;
uint64_t u64;
int64_t s64;
} v;
struct dictEntry *next;
} dictEntry;
typedef struct dictType {
unsigned int (*hashFunction)(const void *key);
void *(*keyDup)(void *privdata, const void *key);
void *(*valDup)(void *privdata, const void *obj);
int (*keyCompare)(void *privdata, const void *key1, const void *key2);
void (*keyDestructor)(void *privdata, void *key);
void (*valDestructor)(void *privdata, void *obj);
} dictType;
/* This is our hash table structure. Every dictionary has two of this as we
* implement incremental rehashing, for the old to the new table. */
typedef struct dictht {
dictEntry **table;
unsigned long size;//桶个数
unsigned long sizemask;//桶掩码。 size-1
unsigned long used;//table中元素总个数
} dictht;
typedef struct dict {
dictType *type;
void *privdata;
dictht ht[2];//ht[0]是供正常使用过的。 ht[1]是供rehash用的。 rehash完之后会将ht[0] = ht[1] && reset(ht[1])
int rehashidx; /* rehashing not in progress if rehashidx == -1 */
int iterators; /* number of iterators currently running 只有iterator->safe==1时才会自增或者自减,普通的iterator不会影响该值*/
} dict;
核心函数:
rehashidx 是-1时表示没有在rehash中。 否则rehashidx就是正在rehash 的桶下标。
dictExpand:扩大hashtable的大小; 这里指桶的大小、 而不是指能够存放的总大小。
dictRehash(dict *d, int n):逐个桶的rehash。n仅表示本次函数调用期望处理的有效桶个数。返回0表示整个hash完。
_dictKeyIndex:查找。分别在ht[0]与ht[1]中查找该key,找到则返回-1; 未找到时若在rehash则返回在ht[1]中的桶下标,否则返回ht[0]中的下标。
key的桶下标计算方式是: dictHashKey(key) & (size - 1)。 其中size总是2倍的方式扩大。 此种计算方式得到的桶下标必定<size。
查找:先在ht[0]中找, 未找到且在rehashing中,则继续在ht[1]中找。 返回找到的桶下标,否则返回-1.
插入:如果查找已成功, 则返回-1、不允许插入; 否则如果在rehash中,则插入到ht[1]中;否则插入到ht[0]中。 插入在桶的头部
在unsafe的迭代过程中(iterators > 0)时, 不允许继续rehash。
迭代过程中允许插入和删除。 插入的/删除的可能不会被遍历到。 但不会引起错误, 只要迭代器当前的元素没被删除即可。
删除时,先查找, 然后从链表总删掉。
typedef struct dictIterator {
dict *d;
int table; //d的ht的索引。 0或者1
int index; //d->ht[table]的桶下标
int safe; //为1时, 会影响到d->iterators
dictEntry *entry, *nextEntry;
long long fingerprint; /* unsafe iterator fingerprint for misuse detection */
} dictIterator;
当未设置safe时, 就必须保证fingerprint在release时相同, 就是说d未被增删元素、未被rehash
dictEntry *dictNext(dictIterator *iter)
{
while (1) {
if (iter->entry == NULL) {
dictht *ht = &iter->d->ht[iter->table];
if (iter->index == -1 && iter->table == 0) {刚被初始化、第一次调用时
if (iter->safe)
iter->d->iterators++;
else
iter->fingerprint = dictFingerprint(iter->d);
}
iter->index++;//该bucket的entry为null,因此继续到下一个bucket。
if (iter->index >= (signed) ht->size) {//桶下标溢出, 则到ht[1]中从bucket 0开始
if (dictIsRehashing(iter->d) && iter->table == 0) {
iter->table++;
iter->index = 0;
ht = &iter->d->ht[1];
} else {
break;
}
}
iter->entry = ht->table[iter->index];
} else {
iter->entry = iter->nextEntry;
}
if (iter->entry) {
/* We need to save the 'next' here, the iterator user
* may delete the entry we are returning. */
iter->nextEntry = iter->entry->next;
return iter->entry;
}
}
return NULL;
}