107 int64_t occupied_and_removed_slots_;
128#define LOAD_FACTOR 1, 2
129 LoadFactor max_load_factor_ = LoadFactor(
LOAD_FACTOR);
144 Key *keys_ =
nullptr;
147#define VECTOR_SET_SLOT_PROBING_BEGIN(HASH, R_SLOT) \
148 SLOT_PROBING_BEGIN (ProbingStrategy, HASH, slot_mask_, SLOT_INDEX) \
149 auto &R_SLOT = slots_[SLOT_INDEX];
150#define VECTOR_SET_SLOT_PROBING_END() SLOT_PROBING_END()
160 occupied_and_removed_slots_(0),
163 slots_(1, allocator),
178 VectorSet(
const std::initializer_list<Key> &keys, Allocator allocator = {})
186 if (keys_ !=
nullptr) {
187 this->deallocate_keys_array(keys_);
193 keys_ = this->allocate_keys_array(other.usable_slots_);
198 this->deallocate_keys_array(keys_);
202 removed_slots_ = other.removed_slots_;
203 occupied_and_removed_slots_ = other.occupied_and_removed_slots_;
204 usable_slots_ = other.usable_slots_;
205 slot_mask_ = other.slot_mask_;
207 is_equal_ = other.is_equal_;
211 : removed_slots_(other.removed_slots_),
212 occupied_and_removed_slots_(other.occupied_and_removed_slots_),
213 usable_slots_(other.usable_slots_),
214 slot_mask_(other.slot_mask_),
215 slots_(std::move(other.slots_)),
218 other.removed_slots_ = 0;
219 other.occupied_and_removed_slots_ = 0;
220 other.usable_slots_ = 0;
221 other.slot_mask_ = 0;
223 other.keys_ =
nullptr;
269 this->add_new__impl(key, hash_(key));
273 this->add_new__impl(std::move(key), hash_(key));
288 return this->
add_as(std::move(key));
290 template<
typename ForwardKey>
bool add_as(ForwardKey &&key)
292 return this->add__impl(std::forward<ForwardKey>(key), hash_(key));
304 for (
const Key &key : keys) {
318 template<
typename ForwardKey>
bool contains_as(
const ForwardKey &key)
const
320 return this->contains__impl(key, hash_(key));
333 template<
typename ForwardKey>
bool remove_as(
const ForwardKey &key)
335 return this->remove__impl(key, hash_(key));
348 this->remove_contained__impl(key, hash_(key));
360 for (Slot &slot : slots_) {
361 if (slot.is_occupied()) {
362 const int64_t index = slot.index();
363 const Key &key = keys_[index];
364 if (predicate(key)) {
365 this->remove_key_internal(slot);
369 return prev_size - this->
size();
378 return this->pop__impl();
391 return this->index_of__impl(key, hash_(key));
404 return this->index_of_try__impl(key, hash_(key));
421 return this->index_of_or_add__impl(std::forward<ForwardKey>(key), hash_(key));
449 const int64_t index = this->index_of_try__impl(key, hash_(key));
451 return keys_ + index;
471 return keys_ + this->
size();
496 return occupied_and_removed_slots_ - removed_slots_;
504 return occupied_and_removed_slots_ == removed_slots_;
512 return slots_.size();
520 return removed_slots_;
528 return sizeof(Slot) +
sizeof(
Key);
537 return int64_t(
sizeof(Slot) * slots_.size() +
sizeof(
Key) * usable_slots_);
545 if (usable_slots_ < n) {
546 this->realloc_and_reinsert(n);
556 for (Slot &slot : slots_) {
562 occupied_and_removed_slots_ = 0;
570 std::destroy_at(
this);
580 return this->count_collisions__impl(key, hash_(key));
586 int64_t total_slots, usable_slots;
587 max_load_factor_.compute_total_and_usable_slots(
593 if (this->
size() == 0) {
595 slots_.reinitialize(total_slots);
596 if (keys_ !=
nullptr) {
597 this->deallocate_keys_array(keys_);
600 keys_ = this->allocate_keys_array(usable_slots);
603 this->noexcept_reset();
607 occupied_and_removed_slots_ = 0;
608 usable_slots_ = usable_slots;
609 slot_mask_ = new_slot_mask;
613 SlotArray new_slots(total_slots);
616 for (Slot &slot : slots_) {
617 if (slot.is_occupied()) {
618 this->add_after_grow(slot, new_slots, new_slot_mask);
622 slots_ = std::move(new_slots);
625 this->noexcept_reset();
629 Key *new_keys = this->allocate_keys_array(usable_slots);
634 this->deallocate_keys_array(new_keys);
635 this->noexcept_reset();
638 this->deallocate_keys_array(keys_);
641 occupied_and_removed_slots_ -= removed_slots_;
642 usable_slots_ = usable_slots;
644 slot_mask_ = new_slot_mask;
647 void add_after_grow(Slot &old_slot, SlotArray &new_slots,
const uint64_t new_slot_mask)
649 const Key &key = keys_[old_slot.index()];
653 Slot &slot = new_slots[slot_index];
654 if (slot.is_empty()) {
655 slot.occupy(old_slot.index(),
hash);
662 void noexcept_reset() noexcept
664 Allocator allocator = slots_.allocator();
666 new (
this)
VectorSet(NoExceptConstructor(), allocator);
669 template<
typename ForwardKey>
670 bool contains__impl(
const ForwardKey &key,
const uint64_t hash)
const
673 if (slot.is_empty()) {
676 if (slot.contains(key, is_equal_,
hash, keys_)) {
683 template<
typename ForwardKey>
void add_new__impl(ForwardKey &&key,
const uint64_t hash)
687 this->ensure_can_add();
690 if (slot.is_empty()) {
692 Key *dst = keys_ + index;
693 new (dst)
Key(std::forward<ForwardKey>(key));
695 slot.occupy(index,
hash);
696 occupied_and_removed_slots_++;
703 template<
typename ForwardKey>
bool add__impl(ForwardKey &&key,
const uint64_t hash)
705 this->ensure_can_add();
708 if (slot.is_empty()) {
710 Key *dst = keys_ + index;
711 new (dst)
Key(std::forward<ForwardKey>(key));
713 slot.occupy(index,
hash);
714 occupied_and_removed_slots_++;
717 if (slot.contains(key, is_equal_,
hash, keys_)) {
724 template<
typename ForwardKey>
730 if (slot.contains(key, is_equal_,
hash, keys_)) {
737 template<
typename ForwardKey>
741 if (slot.contains(key, is_equal_,
hash, keys_)) {
744 if (slot.is_empty()) {
751 template<
typename ForwardKey>
754 this->ensure_can_add();
757 if (slot.contains(key, is_equal_,
hash, keys_)) {
760 if (slot.is_empty()) {
762 Key *dst = keys_ + index;
763 new (dst)
Key(std::forward<ForwardKey>(key));
765 slot.occupy(index,
hash);
766 occupied_and_removed_slots_++;
778 Key key = std::move(keys_[index_to_pop]);
779 keys_[index_to_pop].~Key();
785 if (slot.has_index(index_to_pop)) {
793 template<
typename ForwardKey>
bool remove__impl(
const ForwardKey &key,
const uint64_t hash)
796 if (slot.contains(key, is_equal_,
hash, keys_)) {
797 this->remove_key_internal(slot);
800 if (slot.is_empty()) {
807 template<
typename ForwardKey>
808 void remove_contained__impl(
const ForwardKey &key,
const uint64_t hash)
813 if (slot.contains(key, is_equal_,
hash, keys_)) {
814 this->remove_key_internal(slot);
821 void remove_key_internal(Slot &slot)
823 int64_t index_to_remove = slot.index();
825 int64_t last_element_index = size - 1;
827 if (index_to_remove < last_element_index) {
828 keys_[index_to_remove] = std::move(keys_[last_element_index]);
829 this->update_slot_index(keys_[index_to_remove], last_element_index, index_to_remove);
832 keys_[last_element_index].~Key();
838 void update_slot_index(
const Key &key,
const int64_t old_index,
const int64_t new_index)
842 if (slot.has_index(old_index)) {
843 slot.update_index(new_index);
850 template<
typename ForwardKey>
856 if (slot.contains(key, is_equal_,
hash, keys_)) {
859 if (slot.is_empty()) {
867 void ensure_can_add()
869 if (occupied_and_removed_slots_ >= usable_slots_) {
870 this->realloc_and_reinsert(this->
size() + 1);
871 BLI_assert(occupied_and_removed_slots_ < usable_slots_);
877 return static_cast<Key *
>(
878 slots_.allocator().allocate(
sizeof(
Key) *
size_t(size),
alignof(
Key), AT));
881 void deallocate_keys_array(
Key *keys)
883 slots_.allocator().deallocate(keys);