m_cell = Details::find(hash, m_table);
if (!m_cell)
return;
- m_value = m_cell->value.load(turf::Consume);
- if (m_value != Value(ValueTraits::Redirect))
- return; // Found an existing value
+ Value value = m_cell->value.load(turf::Consume);
+ if (value != Value(ValueTraits::Redirect)) {
+ // Found an existing value
+ m_value = value;
+ return;
+ }
// We've encountered a Redirect value. Help finish the migration.
TURF_TRACE(ConcurrentMap_Leapfrog, 1, "[Mutator] find was redirected", uptr(m_table), 0);
m_table->jobCoordinator.participate();
}
case Details::InsertResult_AlreadyFound: {
// The hash was already found in the table.
- m_value = m_cell->value.load(turf::Consume);
- if (m_value == Value(ValueTraits::Redirect)) {
+ Value value = m_cell->value.load(turf::Consume);
+ if (value == Value(ValueTraits::Redirect)) {
// We've encountered a Redirect value.
TURF_TRACE(ConcurrentMap_Leapfrog, 3, "[Mutator] insertOrFind was redirected", uptr(m_table), uptr(m_value));
break; // Help finish the migration.
}
- return; // Found an existing value
+ // Found an existing value
+ m_value = value;
+ return;
}
case Details::InsertResult_Overflow: {
+ // Unlike ConcurrentMap_Linear, we don't need to keep track of & pass a "mustDouble" flag.
+ // Passing overflowIdx is sufficient to prevent an infinite loop here.
+ // It defines the start of the range of cells to check while estimating total cells in use.
+ // After the first migration, deleted keys are purged, so if we hit this line during the
+ // second loop iteration, every cell in the range will be in use, thus the estimate will be 100%.
+ // (Concurrent deletes could result in further iterations, but it will eventually settle.)
Details::beginTableMigration(m_map, m_table, overflowIdx);
break;
}
}
}
- void setValue(Value desired) {
+ void assignValue(Value desired) {
exchangeValue(desired);
}
}
}
- Value set(Key key, Value desired) {
+ Value assign(Key key, Value desired) {
Mutator iter(*this, key);
return iter.exchangeValue(desired);
}