- s32 prevRemainingValues = s32(-1);
- if (oldValue == Value(ValueTraits::NullValue)) {
- // It's a deleted or newly initialized cell.
- // Decrement remainingValues to ensure we have permission to (re)insert a value.
- prevRemainingValues = m_table->valuesRemaining.fetchSub(1, turf::Relaxed);
- if (prevRemainingValues <= 0) {
- TURF_TRACE(ConcurrentMap_Linear, 5, "[Mutator::exchangeValue] ran out of valuesRemaining", uptr(m_table),
- prevRemainingValues);
- // Can't (re)insert any more values.
- // There are two ways this can happen. One with a TableMigration already in progress, and one without:
- // 1. A TableMigration puts a cap on the number of values late-arriving threads are allowed to insert.
- // 2. Two threads race to insert the same key, and it's the last free cell in the table.
- // (Note: We could get tid of the valuesRemaining counter by handling the possibility of migration
- // failure,
- // as LeapFrog and Grampa do...)
- m_table->valuesRemaining.fetchAdd(1, turf::Relaxed); // Undo valuesRemaining decrement
- // Since we don't know whether there's already a TableMigration in progress, always attempt to start one
- // here:
- Details::beginTableMigration(m_map, m_table);
- goto helpMigrate;
- }
- }