mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
Split logic for resizing empty and allocated tables.
In the follow up changes these functions would have even more difference in the implementation. PiperOrigin-RevId: 924857072 Change-Id: I637e532b1e6ed1e7fe5d700686d9775cc0e8ec11
This commit is contained in:
committed by
Copybara-Service
parent
a30bcb2c51
commit
19937ca3e5
@@ -681,11 +681,6 @@ void ClearBackingArray(CommonFields& c,
|
||||
|
||||
namespace {
|
||||
|
||||
enum class ResizeNonSooMode {
|
||||
kGuaranteedEmpty,
|
||||
kGuaranteedAllocated,
|
||||
};
|
||||
|
||||
// Iterates over full slots in old table, finds new positions for them and
|
||||
// transfers the slots.
|
||||
// This function is used for reserving or rehashing non-empty tables.
|
||||
@@ -795,23 +790,22 @@ BackingArrayPtrs AllocBackingArray(CommonFields& common,
|
||||
mem + layout.slot_offset()};
|
||||
}
|
||||
|
||||
template <ResizeNonSooMode kMode>
|
||||
void ResizeNonSooImpl(CommonFields& common,
|
||||
const PolicyFunctions& __restrict policy,
|
||||
size_t new_capacity, HashtablezInfoHandle infoz) {
|
||||
void ResizeEmptyNonAllocatedTableImpl(CommonFields& common,
|
||||
const PolicyFunctions& __restrict policy,
|
||||
size_t new_capacity, bool force_infoz) {
|
||||
ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity));
|
||||
ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity());
|
||||
|
||||
[[maybe_unused]] const size_t old_capacity = common.capacity();
|
||||
[[maybe_unused]] ctrl_t* old_ctrl;
|
||||
[[maybe_unused]] void* old_slots;
|
||||
if constexpr (kMode == ResizeNonSooMode::kGuaranteedAllocated) {
|
||||
old_ctrl = common.control();
|
||||
old_slots = common.slot_array();
|
||||
}
|
||||
|
||||
ABSL_SWISSTABLE_ASSERT(!force_infoz || policy.soo_enabled);
|
||||
ABSL_SWISSTABLE_ASSERT(common.capacity() == policy.soo_capacity());
|
||||
ABSL_SWISSTABLE_ASSERT(common.empty());
|
||||
const size_t slot_size = policy.slot_size;
|
||||
[[maybe_unused]] const size_t slot_align = policy.slot_align;
|
||||
HashtablezInfoHandle infoz;
|
||||
const bool should_sample =
|
||||
policy.is_hashtablez_eligible && (force_infoz || ShouldSampleNextTable());
|
||||
if (ABSL_PREDICT_FALSE(should_sample)) {
|
||||
infoz = ForcedTrySample(slot_size, policy.key_size, policy.value_size,
|
||||
policy.soo_capacity());
|
||||
}
|
||||
const bool has_infoz = infoz.IsSampled();
|
||||
void* alloc = policy.get_char_alloc(common);
|
||||
|
||||
@@ -822,53 +816,17 @@ void ResizeNonSooImpl(CommonFields& common,
|
||||
common.set_slots(new_slots);
|
||||
common.generate_new_seed(has_infoz);
|
||||
|
||||
size_t total_probe_length = 0;
|
||||
ResetCtrl(common, slot_size);
|
||||
ABSL_SWISSTABLE_ASSERT(kMode != ResizeNonSooMode::kGuaranteedEmpty ||
|
||||
old_capacity == policy.soo_capacity());
|
||||
ABSL_SWISSTABLE_ASSERT(kMode != ResizeNonSooMode::kGuaranteedAllocated ||
|
||||
old_capacity > 0);
|
||||
if constexpr (kMode == ResizeNonSooMode::kGuaranteedAllocated) {
|
||||
total_probe_length = FindNewPositionsAndTransferSlots(
|
||||
common, policy, old_ctrl, old_slots, old_capacity);
|
||||
(*policy.dealloc)(alloc, old_capacity, old_ctrl, slot_size, slot_align,
|
||||
has_infoz);
|
||||
if (HasGrowthInfoForCapacity(new_capacity)) {
|
||||
ResetGrowthLeft(GetGrowthInfoFromControl(new_ctrl), new_capacity,
|
||||
common.size());
|
||||
}
|
||||
} else {
|
||||
if (HasGrowthInfoForCapacity(new_capacity)) {
|
||||
GetGrowthInfoFromControl(new_ctrl).InitGrowthLeftNoDeleted(
|
||||
CapacityToGrowth(new_capacity));
|
||||
}
|
||||
if (HasGrowthInfoForCapacity(new_capacity)) {
|
||||
GetGrowthInfoFromControl(new_ctrl).InitGrowthLeftNoDeleted(
|
||||
CapacityToGrowth(new_capacity));
|
||||
}
|
||||
|
||||
if (ABSL_PREDICT_FALSE(has_infoz)) {
|
||||
ReportResizeToInfoz(common, infoz, total_probe_length);
|
||||
ReportResizeToInfoz(common, infoz, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ResizeEmptyNonAllocatedTableImpl(CommonFields& common,
|
||||
const PolicyFunctions& __restrict policy,
|
||||
size_t new_capacity, bool force_infoz) {
|
||||
ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity));
|
||||
ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity());
|
||||
ABSL_SWISSTABLE_ASSERT(!force_infoz || policy.soo_enabled);
|
||||
ABSL_SWISSTABLE_ASSERT(common.capacity() <= policy.soo_capacity());
|
||||
ABSL_SWISSTABLE_ASSERT(common.empty());
|
||||
const size_t slot_size = policy.slot_size;
|
||||
HashtablezInfoHandle infoz;
|
||||
const bool should_sample =
|
||||
policy.is_hashtablez_eligible && (force_infoz || ShouldSampleNextTable());
|
||||
if (ABSL_PREDICT_FALSE(should_sample)) {
|
||||
infoz = ForcedTrySample(slot_size, policy.key_size, policy.value_size,
|
||||
policy.soo_capacity());
|
||||
}
|
||||
ResizeNonSooImpl<ResizeNonSooMode::kGuaranteedEmpty>(common, policy,
|
||||
new_capacity, infoz);
|
||||
}
|
||||
|
||||
// If the table was SOO, initializes new control bytes and transfers slot.
|
||||
// After transferring the slot, sets control and slots in CommonFields.
|
||||
// It is rare to resize an SOO table with one element to a large size.
|
||||
@@ -1760,8 +1718,41 @@ void* GetRefForEmptyClass(CommonFields& common) {
|
||||
void ResizeAllocatedTableWithSeedChange(
|
||||
CommonFields& common, const PolicyFunctions& __restrict policy,
|
||||
size_t new_capacity) {
|
||||
ResizeNonSooImpl<ResizeNonSooMode::kGuaranteedAllocated>(
|
||||
common, policy, new_capacity, common.infoz());
|
||||
ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity));
|
||||
ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity());
|
||||
|
||||
const size_t old_capacity = common.capacity();
|
||||
ctrl_t* const old_ctrl = common.control();
|
||||
void* const old_slots = common.slot_array();
|
||||
|
||||
const size_t slot_size = policy.slot_size;
|
||||
const size_t slot_align = policy.slot_align;
|
||||
HashtablezInfoHandle infoz = common.infoz();
|
||||
const bool has_infoz = infoz.IsSampled();
|
||||
void* alloc = policy.get_char_alloc(common);
|
||||
|
||||
common.set_capacity(new_capacity);
|
||||
const auto [new_ctrl, new_slots] =
|
||||
AllocBackingArray(common, policy, new_capacity, has_infoz, alloc);
|
||||
common.set_control(new_ctrl);
|
||||
common.set_slots(new_slots);
|
||||
common.generate_new_seed(has_infoz);
|
||||
|
||||
size_t total_probe_length = 0;
|
||||
ResetCtrl(common, slot_size);
|
||||
ABSL_SWISSTABLE_ASSERT(old_capacity > 0);
|
||||
total_probe_length = FindNewPositionsAndTransferSlots(
|
||||
common, policy, old_ctrl, old_slots, old_capacity);
|
||||
(*policy.dealloc)(alloc, old_capacity, old_ctrl, slot_size, slot_align,
|
||||
has_infoz);
|
||||
if (HasGrowthInfoForCapacity(new_capacity)) {
|
||||
ResetGrowthLeft(GetGrowthInfoFromControl(new_ctrl), new_capacity,
|
||||
common.size());
|
||||
}
|
||||
|
||||
if (ABSL_PREDICT_FALSE(has_infoz)) {
|
||||
ReportResizeToInfoz(common, infoz, total_probe_length);
|
||||
}
|
||||
}
|
||||
|
||||
void ReserveEmptyNonAllocatedTableToFitBucketCount(
|
||||
|
||||
Reference in New Issue
Block a user