/* Initialize the hash table */ 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; }
/* 初始化字典 */ 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; // -1 表示没有在进行 rehash d->iterators = 0; // 0 表示没有迭代器在进行迭代 return DICT_OK; // 返回成功信号 }
/* Initialize the hash table */ static int _dictInit(dict *ht, dictType *type, void *privDataPtr) { _dictReset(ht); ht->type = type; ht->privdata = privDataPtr; return DICT_OK; }
/* 删除字典中指定的哈希表 * * Destroy an entire dictionary * * Args: * d 被删除的哈希表所属的字典 * ht 被删除的哈希表 * * Returns: * DICT_OK 删除成功(这个函数不可能失败) */ int _dictClear(dict *d, dictht *ht) { unsigned long i; // 遍历整个哈希表,删除所有节点链 /* Free all the elements */ for (i = 0; i < ht->size && ht->used > 0; i++) { dictEntry *he, *nextHe; // 碰到空节点链,跳到下一个节点链去 if ((he = ht->table[i]) == NULL) continue; // 如果节点链非空,就遍历删除所有节点 while(he) { nextHe = he->next; dictFreeKey(d, he); // 释放 key 空间 dictFreeVal(d, he); // 释放 value 空间 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 */ }
/* Destroy an entire dictionary */ int _dictClear(dict *d, dictht *ht) { #ifdef _WIN32 size_t i; #else unsigned long i; #endif /* Free all the elements */ for (i = 0; i < ht->size && ht->used > 0; i++) { dictEntry *he, *nextHe; if ((he = ht->table[i]) == NULL) continue; while(he) { nextHe = he->next; dictFreeEntryKey(d, he); dictFreeEntryVal(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 */ }
/* 字典(的哈希表) rehash 函数 * * Args: * d * n 要执行 rehash 的元素数量 * * Returns: * 0 所有元素 rehash 完毕 * 1 还有元素没有 rehash */ int dictRehash(dict *d, int n) { if (!dictIsRehashing(d)) return 0; while(n--) { dictEntry *de, *nextde; // 0 号哈希表的所有元素 rehash 完毕? if (d->ht[0].used == 0) { zfree(d->ht[0].table); // 替换 1 号为 0 号 d->ht[0] = d->ht[1]; _dictReset(&d->ht[1]); // 重置 1 号哈希表 d->rehashidx = -1; // 重置 rehash flag return 0; } /* Note that rehashidx can't overflow as we are sure there are more * elements because ht[0].used != 0 */ assert(d->ht[0].size > (unsigned)d->rehashidx); // 略过所有空链 while(d->ht[0].table[d->rehashidx] == NULL) d->rehashidx++; // 指向链头 de = d->ht[0].table[d->rehashidx]; // 将链表内的所有节点移动到 1 号哈希表 while(de) { unsigned int h; nextde = de->next; // 计算新的地址(用于 1 号哈希表) h = dictHashKey(d, de->key) & d->ht[1].sizemask; de->next = d->ht[1].table[h]; // 更新 next 指针 d->ht[1].table[h] = de; // 移动 d->ht[0].used--; // 更新 0 号表计算器 d->ht[1].used++; // 更新 1 号表计算器 de = nextde; } d->ht[0].table[d->rehashidx] = NULL; // 清空链头 d->rehashidx++; // 更新索引 } return 1; }
//执行一次rehash操作,一般在检查到该字典的rehash标记被设置之后调用该函数 //这里的参数n表示至少执行多少bucket的移动(reahash),每次移动从rehashidx开始 int dictRehash(dict *d, int n) { if (!dictIsRehashing(d)) return 0; while(n--) { dictEntry *de, *nextde; /* Check if we already rehashed the whole table... */ //如果已经全部移动了,说明这一次rehash操作执行完成了 //释放ht[0],然后重新将移动之后的ht[1]替换,这样保证不再rehash操作 //的时候都是使用ht[0]保存新添加的元素 if (d->ht[0].used == 0) { zfree(d->ht[0].table); //复制&重置 d->ht[0] = d->ht[1]; _dictReset(&d->ht[1]); d->rehashidx = -1; return 0; } /* Note that rehashidx can't overflow as we are sure there are more * elements because ht[0].used != 0 */ //在rehash过程中,rehashidx保存的是上一次移动的bucket的下标 //这样在下一次移动的时候从rehashidx开始 assert(d->ht[0].size > (unsigned)d->rehashidx); //跳过没有任何元素的bucket while(d->ht[0].table[d->rehashidx] == NULL) d->rehashidx++; de = d->ht[0].table[d->rehashidx]; /* Move all the keys in this bucket from the old to the new hash HT */ //将旧哈希表ht[0]中的每一个bucket上的每一个entry都移动到ht[1]上 //因为同一个entry在两个表定位的bucket不同,所以需要重新hash,然后添加到bucket //中entry链表的表头 while(de) { unsigned int h; nextde = de->next; /* Get the index in the new hash table */ h = dictHashKey(d, de->key) & d->ht[1].sizemask; de->next = d->ht[1].table[h]; d->ht[1].table[h] = de; d->ht[0].used--; d->ht[1].used++; de = nextde; } d->ht[0].table[d->rehashidx] = NULL; d->rehashidx++; } return 1; }
/* Performs N steps of incremental rehashing. Returns 1 if there are still * keys to move from the old to the new hash table, otherwise 0 is returned. * Note that a rehashing step consists in moving a bucket (that may have more * thank one key as we use chaining) from the old to the new hash table. */ int dictRehash(dict *d, int n) { if (!dictIsRehashing(d)) return 0; while(n--) { dictEntry *de, *nextde; /* Check if we already rehashed the whole table... */ if (d->ht[0].used == 0) { free(d->ht[0].table); d->ht[0] = d->ht[1]; _dictReset(&d->ht[1]); d->rehashidx = -1; return 0; } /* Note that rehashidx can't overflow as we are sure there are more * elements because ht[0].used != 0 */ assert(d->ht[0].size > (unsigned)d->rehashidx); while(d->ht[0].table[d->rehashidx] == NULL) d->rehashidx++; de = d->ht[0].table[d->rehashidx]; /* Move all the keys in this bucket from the old to the new hash HT */ while(de) { unsigned int h; nextde = de->next; /* Get the index in the new hash table */ h = dictHashKey(d, de->key) & d->ht[1].sizemask; de->next = d->ht[1].table[h]; d->ht[1].table[h] = de; d->ht[0].used--; d->ht[1].used++; de = nextde; } d->ht[0].table[d->rehashidx] = NULL; d->rehashidx++; } return 1; }
/* Destroy an entire hash table */ static int _dictClear(dict *ht) { uint32_t i; /* Free all the elements */ for (i = 0; i < ht->size && ht->used > 0; i++) { dictEntry *he, *nextHe; if ((he = ht->table[i]) == NULL) continue; while(he) { nextHe = he->next; dictFreeEntryKey(ht, he); dictFreeEntryVal(ht, he); free(he); ht->used--; he = nextHe; } } /* Free the table and the allocated cache structure */ free(ht->table); /* Re-initialize the table */ _dictReset(ht); return DICT_OK; /* never fails */ }