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 * than one key as we use chaining) from the old to the new hash table, however * since part of the hash table may be composed of empty spaces, it is not * guaranteed t
| 357 | * will visit at max N*10 empty buckets in total, otherwise the amount of |
| 358 | * work it does would be unbound and the function may block for a long time. */ |
| 359 | int dictRehash(dict *d, int n) { |
| 360 | int empty_visits = n*10; /* Max number of empty buckets to visit. */ |
| 361 | if (!dictIsRehashing(d)) return 0; |
| 362 | if (d->asyncdata) return 0; |
| 363 | |
| 364 | while(n-- && d->ht[0].used != 0) { |
| 365 | dictEntry *de, *nextde; |
| 366 | |
| 367 | /* Note that rehashidx can't overflow as we are sure there are more |
| 368 | * elements because ht[0].used != 0 */ |
| 369 | while(d->ht[0].table[d->rehashidx] == NULL) { |
| 370 | d->rehashidx++; |
| 371 | if (--empty_visits == 0) return 1; |
| 372 | } |
| 373 | de = d->ht[0].table[d->rehashidx]; |
| 374 | /* Move all the keys in this bucket from the old to the new hash HT */ |
| 375 | while(de) { |
| 376 | uint64_t h; |
| 377 | |
| 378 | nextde = de->next; |
| 379 | /* Get the index in the new hash table */ |
| 380 | h = dictHashKey(d, de->key) & d->ht[1].sizemask; |
| 381 | de->next = d->ht[1].table[h]; |
| 382 | d->ht[1].table[h] = de; |
| 383 | d->ht[0].used--; |
| 384 | d->ht[1].used++; |
| 385 | de = nextde; |
| 386 | } |
| 387 | d->ht[0].table[d->rehashidx] = NULL; |
| 388 | d->rehashidx++; |
| 389 | } |
| 390 | |
| 391 | /* Check if we already rehashed the whole table... */ |
| 392 | if (d->ht[0].used == 0) { |
| 393 | asyncFreeDictTable(d->ht[0].table); |
| 394 | d->ht[0] = d->ht[1]; |
| 395 | _dictReset(&d->ht[1]); |
| 396 | d->rehashidx = -1; |
| 397 | return 0; |
| 398 | } |
| 399 | |
| 400 | /* More to rehash... */ |
| 401 | return 1; |
| 402 | } |
| 403 | |
| 404 | dictAsyncRehashCtl::dictAsyncRehashCtl(struct dict *d, dictAsyncRehashCtl *next) : dict(d), next(next) { |
| 405 | queue.reserve(c_targetQueueSize); |
no test coverage detected