当前位置:网站首页>redis源码分析 2 迭代器
redis源码分析 2 迭代器
2022-07-17 05:08:00 【HjasnJH】
迭代器,在很多的高级语言都会有该实现,其作用就是实现对容器的遍历
迭代器结构:
typedef struct dictIterator {
dict *d;
long index;
int table, safe; // safe 是否是安全的迭代器
dictEntry *entry, *nextEntry;
/* unsafe iterator fingerprint for misuse detection. */
long long fingerprint;
} dictIterator;
通过safe来区分 safe=1为安全迭代器
entry与nextEntry两个指针分别指向Hash冲突后的两个父子节点。 如果在安全模式下, 删除了entry节点, nextEntry字段可以保证后续迭代数据不丢失
迭代器的种类
普通的迭代器:只遍历数据
安全的迭代器:遍历的同时删除数据
迭代器的操作:
获取迭代器
获取普通迭代器:
dictIterator *dictGetIterator(dict *d)
{
dictIterator *iter = zmalloc(sizeof(*iter));
iter->d = d;
iter->table = 0;
iter->index = -1;
iter->safe = 0;
iter->entry = NULL;
iter->nextEntry = NULL;
return iter;
}不允许对数据进行操作,因为遍历迭代器时会获取dictGetIterator 会获取dictFingerprint ,时整个字典的指纹,如果遍历完成有指纹发生变化,则会导致错误。
这时你可能会问,为啥不是单线程的吗,为什么遍历有可能被其他修改了呢?其实,如果你仔细看,我们对字典的任何插入,查找等操作,都会调用rehashstep,这就有可能导致了字典指纹的变化。
获取安全迭代器:
其实只是相对普通迭代器设置safe标志为1
dictIterator *dictGetSafeIterator(dict *d) {
dictIterator *i = dictGetIterator(d);
i->safe = 1;
return i;
}字典的增删改查操作会调用dictRehashStep函数进行渐进式rehash操作,但是我们看到
static void _dictRehashStep(dict *d) {
if (d->iterators == 0) dictRehash(d,1);
}
其实,rehash的时候,会判断是不是在安全迭代器模式,如果是则不会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++;
if (iter->index >= (long) ht->size) {
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;
}
如果是安全模式:首次遍历iterators 会++ ,表示现在字典在安全遍历,会禁止了rehash
如果不是安全模式:首次则要记录字典的指纹信息。
字典指纹的获取:其实就是将字典转换为一个64位的数组,也可以理解是一种hash
long long dictFingerprint(dict *d) {
long long integers[6], hash = 0;
int j;
integers[0] = (long) d->ht[0].table;
integers[1] = d->ht[0].size;
integers[2] = d->ht[0].used;
integers[3] = (long) d->ht[1].table;
integers[4] = d->ht[1].size;
integers[5] = d->ht[1].used;
/* We hash N integers by summing every successive integer with the integer
* hashing of the previous sum. Basically:
*
* Result = hash(hash(hash(int1)+int2)+int3) ...
*
* This way the same set of integers in a different order will (likely) hash
* to a different number. */
for (j = 0; j < 6; j++) {
hash += integers[j];
/* For the hashing step we use Tomas Wang's 64 bit integer hash. */
hash = (~hash) + (hash << 21); // hash = (hash << 21) - hash - 1;
hash = hash ^ (hash >> 24);
hash = (hash + (hash << 3)) + (hash << 8); // hash * 265
hash = hash ^ (hash >> 14);
hash = (hash + (hash << 2)) + (hash << 4); // hash * 21
hash = hash ^ (hash >> 28);
hash = hash + (hash << 31);
}
return hash;
}释放迭代器
void dictReleaseIterator(dictIterator *iter)
{
if (!(iter->index == -1 && iter->table == 0)) {
if (iter->safe)
iter->d->iterators--;
else
assert(iter->fingerprint == dictFingerprint(iter->d));
}
zfree(iter);
}释放迭代器要将安全模式下iterators++的值减回去,如果不是安全模式,则要判断字典是不是遍历的过程中被修改,修改则触发断言。
最后释放迭代器。
边栏推荐
- Base64 and file conversion
- Applet editor rich text editing and rich text parsing
- ArcGIS 点云(xyz)数据转DEM
- PAT乙级1017: A除以B
- Excel计算本月剩余天数
- Pointer advanced simple summary
- Excel calculates the remaining days of the month
- MySQL optimization
- IText modify PDF Text
- Case summary of rotation chart moving speed (constant speed, slow motion)
猜你喜欢

Wechat applet obtains the week, morning, noon and evening of month, year and day

百度地图 实现 热力图

Internship project 3- change owner

mysql - 索引

小程序云开发表单提交并在页面中获取数据

Applet cloud development form submission and data acquisition in the page

Use echars to realize water drop, ring, segmentation, stacking, organization chart, map outline and other charts

分布式存储-fastdfs

Excel计算本月剩余天数

Uniapp uses uview to realize folding panel
随机推荐
es6新增-运算符的扩展
ES6 latest commonly used knowledge dictionary (which can help you solve interview questions, problems in programming, etc.)
基于PaddleOCR解决文本检测训练模型与inference模型预测效果不一致的问题
Get the multi-functional version of the maximum and minimum values of the internal values of the objects in the array and the full version of the roll call system, and show the effect
ES6 real case deconstruction (multidimensional array object) new case:
Wechat applet status bar
父组件加scoped有时也会影响子组件
js 原生对象加属性
MySQL optimization
Submit the uniapp form (input, radio, picker) to get the parameter value
Excel calculates the remaining days of the month
(elaborate) ES6 remaining parameters, ES6 built-in objects, template string content (detailed example Dictionary) and practical cases of flexible use of the project
Two methods of rotation chart and automatic rotation
Pointer advanced simple summary
Nacos配置管理
Ucharts chart, pie chart, bar chart and line chart are used in uniapp
Internship project 1 - personalized homepage configuration
Baidu map realizes thermal map
CityEngine 三维管道建模教程
Es6最新常用知识宝典(能够帮助你解决面试题困惑,编写程序中出现的问题等)