| 490 | } |
| 491 | |
| 492 | void dictCompleteRehashAsync(dictAsyncRehashCtl *ctl, bool fFree) { |
| 493 | dict *d = ctl->dict; |
| 494 | assert(ctl->done); |
| 495 | |
| 496 | // Unlink ourselves |
| 497 | bool fUnlinked = false; |
| 498 | dictAsyncRehashCtl **pprev = &d->asyncdata; |
| 499 | |
| 500 | while (*pprev != nullptr) { |
| 501 | if (*pprev == ctl) { |
| 502 | *pprev = ctl->next; |
| 503 | fUnlinked = true; |
| 504 | break; |
| 505 | } |
| 506 | pprev = &((*pprev)->next); |
| 507 | } |
| 508 | |
| 509 | if (fUnlinked) { |
| 510 | if (ctl->next != nullptr && ctl->deGCList != nullptr) { |
| 511 | // An older work item may depend on our free list, so pass our free list to them |
| 512 | dictEntry **deGC = &ctl->next->deGCList; |
| 513 | while (*deGC != nullptr) deGC = &((*deGC)->next); |
| 514 | *deGC = ctl->deGCList; |
| 515 | ctl->deGCList = nullptr; |
| 516 | } |
| 517 | } |
| 518 | |
| 519 | if (fUnlinked && !ctl->abondon) { |
| 520 | if (d->ht[0].table != nullptr) { // can be null if we're cleared during the rehash |
| 521 | for (auto &wi : ctl->queue) { |
| 522 | // We need to remove it from the source hash table, and store it in the dest. |
| 523 | // Note that it may have been deleted in the meantime and therefore not exist. |
| 524 | // In this case it will be in the garbage collection list |
| 525 | |
| 526 | dictEntry **pdePrev = &d->ht[0].table[wi.hash & d->ht[0].sizemask]; |
| 527 | while (*pdePrev != nullptr && *pdePrev != wi.de) { |
| 528 | pdePrev = &((*pdePrev)->next); |
| 529 | } |
| 530 | if (*pdePrev != nullptr) { // The element may be NULL if its in the GC list |
| 531 | assert(*pdePrev == wi.de); |
| 532 | *pdePrev = wi.de->next; |
| 533 | // Now link it to the dest hash table |
| 534 | wi.de->next = d->ht[1].table[wi.hash & d->ht[1].sizemask]; |
| 535 | d->ht[1].table[wi.hash & d->ht[1].sizemask] = wi.de; |
| 536 | d->ht[0].used--; |
| 537 | d->ht[1].used++; |
| 538 | } |
| 539 | } |
| 540 | } |
| 541 | |
| 542 | /* Check if we already rehashed the whole table... */ |
| 543 | if (d->ht[0].used == 0 && d->asyncdata == nullptr) { |
| 544 | asyncFreeDictTable(d->ht[0].table); |
| 545 | d->ht[0] = d->ht[1]; |
| 546 | _dictReset(&d->ht[1]); |
| 547 | d->rehashidx = -1; |
| 548 | } |
| 549 | } |
no test coverage detected