Skip to content

Commit

Permalink
Partial roll forward of reentrant validation with the validation itse…
Browse files Browse the repository at this point in the history
…lf disabled. This will make it easier to roll back and forwards in the future (if needed) without causing merge conflicts in unrelated code.

PiperOrigin-RevId: 582059046
Change-Id: I66dc6527e7a0b351367b7a391c2d653fe793143f
  • Loading branch information
ezbr authored and Copybara-Service committed Nov 13, 2023
1 parent c046692 commit 716fa00
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 22 deletions.
33 changes: 21 additions & 12 deletions absl/container/internal/raw_hash_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -2161,7 +2161,7 @@ class raw_hash_set {
alignas(slot_type) unsigned char raw[sizeof(slot_type)];
slot_type* slot = reinterpret_cast<slot_type*>(&raw);

PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...);
construct(slot, std::forward<Args>(args)...);
const auto& elem = PolicyTraits::element(slot);
return PolicyTraits::apply(InsertSlot<true>{*this, std::move(*slot)}, elem);
}
Expand Down Expand Up @@ -2266,7 +2266,7 @@ class raw_hash_set {
// a better match if non-const iterator is passed as an argument.
void erase(iterator it) {
AssertIsFull(it.control(), it.generation(), it.generation_ptr(), "erase()");
PolicyTraits::destroy(&alloc_ref(), it.slot());
destroy(it.slot());
erase_meta_only(it);
}

Expand Down Expand Up @@ -2558,10 +2558,9 @@ class raw_hash_set {
std::pair<iterator, bool> operator()(const K& key, Args&&...) && {
auto res = s.find_or_prepare_insert(key);
if (res.second) {
PolicyTraits::transfer(&s.alloc_ref(), s.slot_array() + res.first,
&slot);
s.transfer(s.slot_array() + res.first, &slot);
} else if (do_destroy) {
PolicyTraits::destroy(&s.alloc_ref(), &slot);
s.destroy(&slot);
}
return {s.iterator_at(res.first), res.second};
}
Expand All @@ -2570,13 +2569,25 @@ class raw_hash_set {
slot_type&& slot;
};

// TODO(b/303305702): re-enable reentrant validation.
template <typename... Args>
inline void construct(slot_type* slot, Args&&... args) {
PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...);
}
inline void destroy(slot_type* slot) {
PolicyTraits::destroy(&alloc_ref(), slot);
}
inline void transfer(slot_type* to, slot_type* from) {
PolicyTraits::transfer(&alloc_ref(), to, from);
}

inline void destroy_slots() {
const size_t cap = capacity();
const ctrl_t* ctrl = control();
slot_type* slot = slot_array();
for (size_t i = 0; i != cap; ++i) {
if (IsFull(ctrl[i])) {
PolicyTraits::destroy(&alloc_ref(), slot + i);
destroy(slot + i);
}
}
}
Expand Down Expand Up @@ -2639,7 +2650,7 @@ class raw_hash_set {
size_t new_i = target.offset;
total_probe_length += target.probe_length;
SetCtrl(common(), new_i, H2(hash), sizeof(slot_type));
PolicyTraits::transfer(&alloc_ref(), new_slots + new_i, old_slots + i);
transfer(new_slots + new_i, old_slots + i);
}
}
if (old_capacity) {
Expand Down Expand Up @@ -2749,7 +2760,7 @@ class raw_hash_set {
reserve(size);
for (iterator it = that.begin(); it != that.end(); ++it) {
insert(std::move(PolicyTraits::element(it.slot())));
PolicyTraits::destroy(&that.alloc_ref(), it.slot());
that.destroy(it.slot());
}
that.dealloc();
that.common() = CommonFields{};
Expand Down Expand Up @@ -2840,8 +2851,7 @@ class raw_hash_set {
// POSTCONDITION: *m.iterator_at(i) == value_type(forward<Args>(args)...).
template <class... Args>
void emplace_at(size_t i, Args&&... args) {
PolicyTraits::construct(&alloc_ref(), slot_array() + i,
std::forward<Args>(args)...);
construct(slot_array() + i, std::forward<Args>(args)...);

assert(PolicyTraits::apply(FindElement{*this}, *iterator_at(i)) ==
iterator_at(i) &&
Expand Down Expand Up @@ -2907,8 +2917,7 @@ class raw_hash_set {
}
static void transfer_slot_fn(void* set, void* dst, void* src) {
auto* h = static_cast<raw_hash_set*>(set);
PolicyTraits::transfer(&h->alloc_ref(), static_cast<slot_type*>(dst),
static_cast<slot_type*>(src));
h->transfer(static_cast<slot_type*>(dst), static_cast<slot_type*>(src));
}
// Note: dealloc_fn will only be used if we have a non-standard allocator.
static void dealloc_fn(CommonFields& common, const PolicyFunctions&) {
Expand Down
16 changes: 6 additions & 10 deletions absl/container/internal/raw_hash_set_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -409,19 +409,15 @@ struct StringTable
using Base::Base;
};

struct IntTable
: raw_hash_set<IntPolicy, hash_default_hash<int64_t>,
std::equal_to<int64_t>, std::allocator<int64_t>> {
using Base = typename IntTable::raw_hash_set;
template <typename T>
struct ValueTable : raw_hash_set<ValuePolicy<T>, hash_default_hash<T>,
std::equal_to<T>, std::allocator<T>> {
using Base = typename ValueTable::raw_hash_set;
using Base::Base;
};

struct Uint8Table
: raw_hash_set<Uint8Policy, hash_default_hash<uint8_t>,
std::equal_to<uint8_t>, std::allocator<uint8_t>> {
using Base = typename Uint8Table::raw_hash_set;
using Base::Base;
};
using IntTable = ValueTable<int64_t>;
using Uint8Table = ValueTable<uint8_t>;

template <typename T>
struct CustomAlloc : std::allocator<T> {
Expand Down

0 comments on commit 716fa00

Please sign in to comment.