Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenlib/BLI_map.hh')
-rw-r--r--source/blender/blenlib/BLI_map.hh441
1 files changed, 197 insertions, 244 deletions
diff --git a/source/blender/blenlib/BLI_map.hh b/source/blender/blenlib/BLI_map.hh
index 9737367ebca..dd375272fdb 100644
--- a/source/blender/blenlib/BLI_map.hh
+++ b/source/blender/blenlib/BLI_map.hh
@@ -67,13 +67,13 @@
* interface as blender::Map. This is useful for benchmarking.
*/
+#include <optional>
#include <unordered_map>
#include "BLI_array.hh"
#include "BLI_hash.hh"
#include "BLI_hash_tables.hh"
#include "BLI_map_slots.hh"
-#include "BLI_optional.hh"
#include "BLI_probing_strategies.hh"
namespace blender {
@@ -92,13 +92,10 @@ template<
* The minimum number of elements that can be stored in this Map without doing a heap
* allocation. This is useful when you expect to have many small maps. However, keep in mind
* that (unlike vector) initializing a map has a O(n) cost in the number of slots.
- *
- * When Key or Value are large, the small buffer optimization is disabled by default to avoid
- * large unexpected allocations on the stack. It can still be enabled explicitely though.
*/
- uint32_t InlineBufferCapacity = (sizeof(Key) + sizeof(Value) < 100) ? 4 : 0,
+ int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(Key) + sizeof(Value)),
/**
- * The strategy used to deal with collistions. They are defined in BLI_probing_strategies.hh.
+ * The strategy used to deal with collisions. They are defined in BLI_probing_strategies.hh.
*/
typename ProbingStrategy = DefaultProbingStrategy,
/**
@@ -129,30 +126,30 @@ class Map {
* Slots are either empty, occupied or removed. The number of occupied slots can be computed by
* subtracting the removed slots from the occupied-and-removed slots.
*/
- uint32_t m_removed_slots;
- uint32_t m_occupied_and_removed_slots;
+ int64_t removed_slots_;
+ int64_t occupied_and_removed_slots_;
/**
* The maximum number of slots that can be used (either occupied or removed) until the set has to
* grow. This is the total number of slots times the max load factor.
*/
- uint32_t m_usable_slots;
+ int64_t usable_slots_;
/**
* The number of slots minus one. This is a bit mask that can be used to turn any integer into a
* valid slot index efficiently.
*/
- uint32_t m_slot_mask;
+ uint64_t slot_mask_;
/** This is called to hash incoming keys. */
- Hash m_hash;
+ Hash hash_;
/** This is called to check equality of two keys. */
- IsEqual m_is_equal;
+ IsEqual is_equal_;
/** The max load factor is 1/2 = 50% by default. */
#define LOAD_FACTOR 1, 2
- LoadFactor m_max_load_factor = LoadFactor(LOAD_FACTOR);
+ LoadFactor max_load_factor_ = LoadFactor(LOAD_FACTOR);
using SlotArray =
Array<Slot, LoadFactor::compute_total_slots(InlineBufferCapacity, LOAD_FACTOR), Allocator>;
#undef LOAD_FACTOR
@@ -161,12 +158,12 @@ class Map {
* This is the array that contains the actual slots. There is always at least one empty slot and
* the size of the array is a power of two.
*/
- SlotArray m_slots;
+ SlotArray slots_;
/** Iterate over a slot index sequence for a given hash. */
#define MAP_SLOT_PROBING_BEGIN(HASH, R_SLOT) \
- SLOT_PROBING_BEGIN (ProbingStrategy, HASH, m_slot_mask, SLOT_INDEX) \
- auto &R_SLOT = m_slots[SLOT_INDEX];
+ SLOT_PROBING_BEGIN (ProbingStrategy, HASH, slot_mask_, SLOT_INDEX) \
+ auto &R_SLOT = slots_[SLOT_INDEX];
#define MAP_SLOT_PROBING_END() SLOT_PROBING_END()
public:
@@ -176,13 +173,13 @@ class Map {
* operation is performed on the first insertion.
*/
Map()
- : m_removed_slots(0),
- m_occupied_and_removed_slots(0),
- m_usable_slots(0),
- m_slot_mask(0),
- m_hash(),
- m_is_equal(),
- m_slots(1)
+ : removed_slots_(0),
+ occupied_and_removed_slots_(0),
+ usable_slots_(0),
+ slot_mask_(0),
+ hash_(),
+ is_equal_(),
+ slots_(1)
{
}
@@ -191,13 +188,13 @@ class Map {
Map(const Map &other) = default;
Map(Map &&other) noexcept
- : m_removed_slots(other.m_removed_slots),
- m_occupied_and_removed_slots(other.m_occupied_and_removed_slots),
- m_usable_slots(other.m_usable_slots),
- m_slot_mask(other.m_slot_mask),
- m_hash(std::move(other.m_hash)),
- m_is_equal(std::move(other.m_is_equal)),
- m_slots(std::move(other.m_slots))
+ : removed_slots_(other.removed_slots_),
+ occupied_and_removed_slots_(other.occupied_and_removed_slots_),
+ usable_slots_(other.usable_slots_),
+ slot_mask_(other.slot_mask_),
+ hash_(std::move(other.hash_)),
+ is_equal_(std::move(other.is_equal_)),
+ slots_(std::move(other.slots_))
{
other.~Map();
new (&other) Map();
@@ -233,19 +230,19 @@ class Map {
*/
void add_new(const Key &key, const Value &value)
{
- this->add_new__impl(key, value, m_hash(key));
+ this->add_new__impl(key, value, hash_(key));
}
void add_new(const Key &key, Value &&value)
{
- this->add_new__impl(key, std::move(value), m_hash(key));
+ this->add_new__impl(key, std::move(value), hash_(key));
}
void add_new(Key &&key, const Value &value)
{
- this->add_new__impl(std::move(key), value, m_hash(key));
+ this->add_new__impl(std::move(key), value, hash_(key));
}
void add_new(Key &&key, Value &&value)
{
- this->add_new__impl(std::move(key), std::move(value), m_hash(key));
+ this->add_new__impl(std::move(key), std::move(value), hash_(key));
}
/**
@@ -271,15 +268,11 @@ class Map {
{
return this->add_as(std::move(key), std::move(value));
}
-
- /**
- * Same as `add`, but accepts other key types that are supported by the hash function.
- */
template<typename ForwardKey, typename ForwardValue>
bool add_as(ForwardKey &&key, ForwardValue &&value)
{
return this->add__impl(
- std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), m_hash(key));
+ std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash_(key));
}
/**
@@ -305,15 +298,11 @@ class Map {
{
return this->add_overwrite_as(std::move(key), std::move(value));
}
-
- /**
- * Same as `add_overwrite`, but accepts other key types that are supported by the hash function.
- */
template<typename ForwardKey, typename ForwardValue>
bool add_overwrite_as(ForwardKey &&key, ForwardValue &&value)
{
return this->add_overwrite__impl(
- std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), m_hash(key));
+ std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash_(key));
}
/**
@@ -325,13 +314,9 @@ class Map {
{
return this->contains_as(key);
}
-
- /**
- * Same as `contains`, but accepts other key types that are supported by the hash function.
- */
template<typename ForwardKey> bool contains_as(const ForwardKey &key) const
{
- return this->contains__impl(key, m_hash(key));
+ return this->contains__impl(key, hash_(key));
}
/**
@@ -344,13 +329,9 @@ class Map {
{
return this->remove_as(key);
}
-
- /**
- * Same as `remove`, but accepts other key types that are supported by the hash function.
- */
template<typename ForwardKey> bool remove_as(const ForwardKey &key)
{
- return this->remove__impl(key, m_hash(key));
+ return this->remove__impl(key, hash_(key));
}
/**
@@ -361,14 +342,9 @@ class Map {
{
this->remove_contained_as(key);
}
-
- /**
- * Same as `remove_contained`, but accepts other key types that are supported by the hash
- * function.
- */
template<typename ForwardKey> void remove_contained_as(const ForwardKey &key)
{
- this->remove_contained__impl(key, m_hash(key));
+ this->remove_contained__impl(key, hash_(key));
}
/**
@@ -379,30 +355,22 @@ class Map {
{
return this->pop_as(key);
}
-
- /**
- * Same as `pop`, but accepts other key types that are supported by the hash function.
- */
template<typename ForwardKey> Value pop_as(const ForwardKey &key)
{
- return this->pop__impl(key, m_hash(key));
+ return this->pop__impl(key, hash_(key));
}
/**
* Get the value that is stored for the given key and remove it from the map. If the key is not
* in the map, a value-less optional is returned.
*/
- Optional<Value> pop_try(const Key &key)
+ std::optional<Value> pop_try(const Key &key)
{
return this->pop_try_as(key);
}
-
- /**
- * Same as `pop_try`, but accepts other key types that are supported by the hash function.
- */
- template<typename ForwardKey> Optional<Value> pop_try_as(const ForwardKey &key)
+ template<typename ForwardKey> std::optional<Value> pop_try_as(const ForwardKey &key)
{
- return this->pop_try__impl(key, m_hash(key));
+ return this->pop_try__impl(key, hash_(key));
}
/**
@@ -417,14 +385,10 @@ class Map {
{
return this->pop_default_as(key, std::move(default_value));
}
-
- /**
- * Same as `pop_default`, but accepts other key types that are supported by the hash function.
- */
template<typename ForwardKey, typename ForwardValue>
Value pop_default_as(const ForwardKey &key, ForwardValue &&default_value)
{
- return this->pop_default__impl(key, std::forward<ForwardValue>(default_value), m_hash(key));
+ return this->pop_default__impl(key, std::forward<ForwardValue>(default_value), hash_(key));
}
/**
@@ -460,17 +424,13 @@ class Map {
{
return this->add_or_modify_as(std::move(key), create_value, modify_value);
}
-
- /**
- * Same as `add_or_modify`, but accepts other key types that are supported by the hash function.
- */
template<typename ForwardKey, typename CreateValueF, typename ModifyValueF>
auto add_or_modify_as(ForwardKey &&key,
const CreateValueF &create_value,
const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
{
return this->add_or_modify__impl(
- std::forward<Key>(key), create_value, modify_value, m_hash(key));
+ std::forward<ForwardKey>(key), create_value, modify_value, hash_(key));
}
/**
@@ -487,17 +447,13 @@ class Map {
{
return this->lookup_ptr_as(key);
}
-
- /**
- * Same as `lookup_ptr`, but accepts other key types that are supported by the hash function.
- */
template<typename ForwardKey> const Value *lookup_ptr_as(const ForwardKey &key) const
{
- return this->lookup_ptr__impl(key, m_hash(key));
+ return this->lookup_ptr__impl(key, hash_(key));
}
template<typename ForwardKey> Value *lookup_ptr_as(const ForwardKey &key)
{
- return const_cast<Value *>(this->lookup_ptr__impl(key, m_hash(key)));
+ return const_cast<Value *>(this->lookup_ptr__impl(key, hash_(key)));
}
/**
@@ -512,10 +468,6 @@ class Map {
{
return this->lookup_as(key);
}
-
- /**
- * Same as `lookup`, but accepts other key types that are supported by the hash function.
- */
template<typename ForwardKey> const Value &lookup_as(const ForwardKey &key) const
{
const Value *ptr = this->lookup_ptr_as(key);
@@ -537,10 +489,6 @@ class Map {
{
return this->lookup_default_as(key, default_value);
}
-
- /**
- * Same as `lookup_default`, but accepts other key types that are supported by the hash function.
- */
template<typename ForwardKey, typename ForwardValue>
Value lookup_default_as(const ForwardKey &key, ForwardValue &&default_value) const
{
@@ -573,16 +521,11 @@ class Map {
{
return this->lookup_or_add_as(std::move(key), std::move(value));
}
-
- /**
- * Same as `lookup_or_add`, but accepts other key types that are supported by the hash
- * function.
- */
template<typename ForwardKey, typename ForwardValue>
Value &lookup_or_add_as(ForwardKey &&key, ForwardValue &&value)
{
return this->lookup_or_add__impl(
- std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), m_hash(key));
+ std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash_(key));
}
/**
@@ -602,15 +545,10 @@ class Map {
{
return this->lookup_or_add_cb_as(std::move(key), create_value);
}
-
- /**
- * Same as `lookup_or_add_cb`, but accepts other key types that are supported by the hash
- * function.
- */
template<typename ForwardKey, typename CreateValueF>
Value &lookup_or_add_cb_as(ForwardKey &&key, const CreateValueF &create_value)
{
- return this->lookup_or_add_cb__impl(std::forward<ForwardKey>(key), create_value, m_hash(key));
+ return this->lookup_or_add_cb__impl(std::forward<ForwardKey>(key), create_value, hash_(key));
}
/**
@@ -625,11 +563,6 @@ class Map {
{
return this->lookup_or_add_default_as(std::move(key));
}
-
- /**
- * Same as `lookup_or_add_default`, but accepts other key types that are supported by the hash
- * function.
- */
template<typename ForwardKey> Value &lookup_or_add_default_as(ForwardKey &&key)
{
return this->lookup_or_add_cb_as(std::forward<ForwardKey>(key), []() { return Value(); });
@@ -641,9 +574,9 @@ class Map {
*/
template<typename FuncT> void foreach_item(const FuncT &func) const
{
- uint32_t size = this->size();
- for (uint32_t i = 0; i < size; i++) {
- const Slot &slot = m_slots[i];
+ int64_t size = slots_.size();
+ for (int64_t i = 0; i < size; i++) {
+ const Slot &slot = slots_[i];
if (slot.is_occupied()) {
const Key &key = *slot.key();
const Value &value = *slot.value();
@@ -657,21 +590,19 @@ class Map {
* This uses the "curiously recurring template pattern" (CRTP).
*/
template<typename SubIterator> struct BaseIterator {
- Slot *m_slots;
- uint32_t m_total_slots;
- uint32_t m_current_slot;
-
- BaseIterator(const Slot *slots, uint32_t total_slots, uint32_t current_slot)
- : m_slots(const_cast<Slot *>(slots)),
- m_total_slots(total_slots),
- m_current_slot(current_slot)
+ Slot *slots_;
+ int64_t total_slots_;
+ int64_t current_slot_;
+
+ BaseIterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
+ : slots_(const_cast<Slot *>(slots)), total_slots_(total_slots), current_slot_(current_slot)
{
}
BaseIterator &operator++()
{
- while (++m_current_slot < m_total_slots) {
- if (m_slots[m_current_slot].is_occupied()) {
+ while (++current_slot_ < total_slots_) {
+ if (slots_[current_slot_].is_occupied()) {
break;
}
}
@@ -680,16 +611,16 @@ class Map {
friend bool operator!=(const BaseIterator &a, const BaseIterator &b)
{
- BLI_assert(a.m_slots == b.m_slots);
- BLI_assert(a.m_total_slots == b.m_total_slots);
- return a.m_current_slot != b.m_current_slot;
+ BLI_assert(a.slots_ == b.slots_);
+ BLI_assert(a.total_slots_ == b.total_slots_);
+ return a.current_slot_ != b.current_slot_;
}
SubIterator begin() const
{
- for (uint32_t i = 0; i < m_total_slots; i++) {
- if (m_slots[i].is_occupied()) {
- return SubIterator(m_slots, m_total_slots, i);
+ for (int64_t i = 0; i < total_slots_; i++) {
+ if (slots_[i].is_occupied()) {
+ return SubIterator(slots_, total_slots_, i);
}
}
return this->end();
@@ -697,18 +628,18 @@ class Map {
SubIterator end() const
{
- return SubIterator(m_slots, m_total_slots, m_total_slots);
+ return SubIterator(slots_, total_slots_, total_slots_);
}
Slot &current_slot() const
{
- return m_slots[m_current_slot];
+ return slots_[current_slot_];
}
};
class KeyIterator final : public BaseIterator<KeyIterator> {
public:
- KeyIterator(const Slot *slots, uint32_t total_slots, uint32_t current_slot)
+ KeyIterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
: BaseIterator<KeyIterator>(slots, total_slots, current_slot)
{
}
@@ -721,7 +652,7 @@ class Map {
class ValueIterator final : public BaseIterator<ValueIterator> {
public:
- ValueIterator(const Slot *slots, uint32_t total_slots, uint32_t current_slot)
+ ValueIterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
: BaseIterator<ValueIterator>(slots, total_slots, current_slot)
{
}
@@ -734,7 +665,7 @@ class Map {
class MutableValueIterator final : public BaseIterator<MutableValueIterator> {
public:
- MutableValueIterator(const Slot *slots, uint32_t total_slots, uint32_t current_slot)
+ MutableValueIterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
: BaseIterator<MutableValueIterator>(slots, total_slots, current_slot)
{
}
@@ -745,18 +676,28 @@ class Map {
}
};
+ struct Item {
+ const Key &key;
+ const Value &value;
+ };
+
+ struct MutableItem {
+ const Key &key;
+ Value &value;
+
+ operator Item() const
+ {
+ return Item{key, value};
+ }
+ };
+
class ItemIterator final : public BaseIterator<ItemIterator> {
public:
- ItemIterator(const Slot *slots, uint32_t total_slots, uint32_t current_slot)
+ ItemIterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
: BaseIterator<ItemIterator>(slots, total_slots, current_slot)
{
}
- struct Item {
- const Key &key;
- const Value &value;
- };
-
Item operator*() const
{
const Slot &slot = this->current_slot();
@@ -766,17 +707,12 @@ class Map {
class MutableItemIterator final : public BaseIterator<MutableItemIterator> {
public:
- MutableItemIterator(const Slot *slots, uint32_t total_slots, uint32_t current_slot)
+ MutableItemIterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
: BaseIterator<MutableItemIterator>(slots, total_slots, current_slot)
{
}
- struct Item {
- const Key &key;
- Value &value;
- };
-
- Item operator*() const
+ MutableItem operator*() const
{
Slot &slot = this->current_slot();
return {*slot.key(), *slot.value()};
@@ -789,7 +725,7 @@ class Map {
*/
KeyIterator keys() const
{
- return KeyIterator(m_slots.data(), m_slots.size(), 0);
+ return KeyIterator(slots_.data(), slots_.size(), 0);
}
/**
@@ -798,7 +734,7 @@ class Map {
*/
ValueIterator values() const
{
- return ValueIterator(m_slots.data(), m_slots.size(), 0);
+ return ValueIterator(slots_.data(), slots_.size(), 0);
}
/**
@@ -807,7 +743,7 @@ class Map {
*/
MutableValueIterator values()
{
- return MutableValueIterator(m_slots.data(), m_slots.size(), 0);
+ return MutableValueIterator(slots_.data(), slots_.size(), 0);
}
/**
@@ -817,7 +753,7 @@ class Map {
*/
ItemIterator items() const
{
- return ItemIterator(m_slots.data(), m_slots.size(), 0);
+ return ItemIterator(slots_.data(), slots_.size(), 0);
}
/**
@@ -829,7 +765,7 @@ class Map {
*/
MutableItemIterator items()
{
- return MutableItemIterator(m_slots.data(), m_slots.size(), 0);
+ return MutableItemIterator(slots_.data(), slots_.size(), 0);
}
/**
@@ -838,15 +774,15 @@ class Map {
void print_stats(StringRef name = "") const
{
HashTableStats stats(*this, this->keys());
- stats.print();
+ stats.print(name);
}
/**
* Return the number of key-value-pairs that are stored in the map.
*/
- uint32_t size() const
+ int64_t size() const
{
- return m_occupied_and_removed_slots - m_removed_slots;
+ return occupied_and_removed_slots_ - removed_slots_;
}
/**
@@ -856,29 +792,29 @@ class Map {
*/
bool is_empty() const
{
- return m_occupied_and_removed_slots == m_removed_slots;
+ return occupied_and_removed_slots_ == removed_slots_;
}
/**
* Returns the number of available slots. This is mostly for debugging purposes.
*/
- uint32_t capacity() const
+ int64_t capacity() const
{
- return m_slots.size();
+ return slots_.size();
}
/**
* Returns the amount of removed slots in the set. This is mostly for debugging purposes.
*/
- uint32_t removed_amount() const
+ int64_t removed_amount() const
{
- return m_removed_slots;
+ return removed_slots_;
}
/**
* Returns the bytes required per element. This is mostly for debugging purposes.
*/
- uint32_t size_per_element() const
+ int64_t size_per_element() const
{
return sizeof(Slot);
}
@@ -887,18 +823,18 @@ class Map {
* Returns the approximate memory requirements of the map in bytes. This becomes more exact the
* larger the map becomes.
*/
- uint32_t size_in_bytes() const
+ int64_t size_in_bytes() const
{
- return sizeof(Slot) * m_slots.size();
+ return (int64_t)(sizeof(Slot) * slots_.size());
}
/**
* Potentially resize the map such that the specified number of elements can be added without
* another grow operation.
*/
- void reserve(uint32_t n)
+ void reserve(int64_t n)
{
- if (m_usable_slots < n) {
+ if (usable_slots_ < n) {
this->realloc_and_reinsert(n);
}
}
@@ -916,35 +852,36 @@ class Map {
* Get the number of collisions that the probing strategy has to go through to find the key or
* determine that it is not in the map.
*/
- uint32_t count_collisions(const Key &key) const
+ int64_t count_collisions(const Key &key) const
{
- return this->count_collisions__impl(key, m_hash(key));
+ return this->count_collisions__impl(key, hash_(key));
}
private:
- BLI_NOINLINE void realloc_and_reinsert(uint32_t min_usable_slots)
+ BLI_NOINLINE void realloc_and_reinsert(int64_t min_usable_slots)
{
- uint32_t total_slots, usable_slots;
- m_max_load_factor.compute_total_and_usable_slots(
+ int64_t total_slots, usable_slots;
+ max_load_factor_.compute_total_and_usable_slots(
SlotArray::inline_buffer_capacity(), min_usable_slots, &total_slots, &usable_slots);
- uint32_t new_slot_mask = total_slots - 1;
+ BLI_assert(total_slots >= 1);
+ const uint64_t new_slot_mask = (uint64_t)total_slots - 1;
/**
* Optimize the case when the map was empty beforehand. We can avoid some copies here.
*/
if (this->size() == 0) {
- m_slots.~Array();
- new (&m_slots) SlotArray(total_slots);
- m_removed_slots = 0;
- m_occupied_and_removed_slots = 0;
- m_usable_slots = usable_slots;
- m_slot_mask = new_slot_mask;
+ slots_.~Array();
+ new (&slots_) SlotArray(total_slots);
+ removed_slots_ = 0;
+ occupied_and_removed_slots_ = 0;
+ usable_slots_ = usable_slots;
+ slot_mask_ = new_slot_mask;
return;
}
SlotArray new_slots(total_slots);
- for (Slot &slot : m_slots) {
+ for (Slot &slot : slots_) {
if (slot.is_occupied()) {
this->add_after_grow_and_destruct_old(slot, new_slots, new_slot_mask);
}
@@ -952,19 +889,19 @@ class Map {
/* All occupied slots have been destructed already and empty/removed slots are assumed to be
* trivially destructible. */
- m_slots.clear_without_destruct();
- m_slots = std::move(new_slots);
- m_occupied_and_removed_slots -= m_removed_slots;
- m_usable_slots = usable_slots;
- m_removed_slots = 0;
- m_slot_mask = new_slot_mask;
+ slots_.clear_without_destruct();
+ slots_ = std::move(new_slots);
+ occupied_and_removed_slots_ -= removed_slots_;
+ usable_slots_ = usable_slots;
+ removed_slots_ = 0;
+ slot_mask_ = new_slot_mask;
}
void add_after_grow_and_destruct_old(Slot &old_slot,
SlotArray &new_slots,
- uint32_t new_slot_mask)
+ uint64_t new_slot_mask)
{
- uint32_t hash = old_slot.get_hash(Hash());
+ uint64_t hash = old_slot.get_hash(Hash());
SLOT_PROBING_BEGIN (ProbingStrategy, hash, new_slot_mask, slot_index) {
Slot &slot = new_slots[slot_index];
if (slot.is_empty()) {
@@ -975,13 +912,13 @@ class Map {
SLOT_PROBING_END();
}
- template<typename ForwardKey> bool contains__impl(const ForwardKey &key, uint32_t hash) const
+ template<typename ForwardKey> bool contains__impl(const ForwardKey &key, uint64_t hash) const
{
MAP_SLOT_PROBING_BEGIN (hash, slot) {
if (slot.is_empty()) {
return false;
}
- if (slot.contains(key, m_is_equal, hash)) {
+ if (slot.contains(key, is_equal_, hash)) {
return true;
}
}
@@ -989,12 +926,12 @@ class Map {
}
template<typename ForwardKey, typename ForwardValue>
- void add_new__impl(ForwardKey &&key, ForwardValue &&value, uint32_t hash)
+ void add_new__impl(ForwardKey &&key, ForwardValue &&value, uint64_t hash)
{
BLI_assert(!this->contains_as(key));
this->ensure_can_add();
- m_occupied_and_removed_slots++;
+ occupied_and_removed_slots_++;
MAP_SLOT_PROBING_BEGIN (hash, slot) {
if (slot.is_empty()) {
@@ -1006,29 +943,29 @@ class Map {
}
template<typename ForwardKey, typename ForwardValue>
- bool add__impl(ForwardKey &&key, ForwardValue &&value, uint32_t hash)
+ bool add__impl(ForwardKey &&key, ForwardValue &&value, uint64_t hash)
{
this->ensure_can_add();
MAP_SLOT_PROBING_BEGIN (hash, slot) {
if (slot.is_empty()) {
slot.occupy(std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash);
- m_occupied_and_removed_slots++;
+ occupied_and_removed_slots_++;
return true;
}
- if (slot.contains(key, m_is_equal, hash)) {
+ if (slot.contains(key, is_equal_, hash)) {
return false;
}
}
MAP_SLOT_PROBING_END();
}
- template<typename ForwardKey> bool remove__impl(const ForwardKey &key, uint32_t hash)
+ template<typename ForwardKey> bool remove__impl(const ForwardKey &key, uint64_t hash)
{
MAP_SLOT_PROBING_BEGIN (hash, slot) {
- if (slot.contains(key, m_is_equal, hash)) {
+ if (slot.contains(key, is_equal_, hash)) {
slot.remove();
- m_removed_slots++;
+ removed_slots_++;
return true;
}
if (slot.is_empty()) {
@@ -1038,14 +975,14 @@ class Map {
MAP_SLOT_PROBING_END();
}
- template<typename ForwardKey> void remove_contained__impl(const ForwardKey &key, uint32_t hash)
+ template<typename ForwardKey> void remove_contained__impl(const ForwardKey &key, uint64_t hash)
{
BLI_assert(this->contains_as(key));
- m_removed_slots++;
+ removed_slots_++;
MAP_SLOT_PROBING_BEGIN (hash, slot) {
- if (slot.contains(key, m_is_equal, hash)) {
+ if (slot.contains(key, is_equal_, hash)) {
slot.remove();
return;
}
@@ -1053,14 +990,14 @@ class Map {
MAP_SLOT_PROBING_END();
}
- template<typename ForwardKey> Value pop__impl(const ForwardKey &key, uint32_t hash)
+ template<typename ForwardKey> Value pop__impl(const ForwardKey &key, uint64_t hash)
{
BLI_assert(this->contains_as(key));
- m_removed_slots++;
+ removed_slots_++;
MAP_SLOT_PROBING_BEGIN (hash, slot) {
- if (slot.contains(key, m_is_equal, hash)) {
+ if (slot.contains(key, is_equal_, hash)) {
Value value = std::move(*slot.value());
slot.remove();
return value;
@@ -1069,13 +1006,14 @@ class Map {
MAP_SLOT_PROBING_END();
}
- template<typename ForwardKey> Optional<Value> pop_try__impl(const ForwardKey &key, uint32_t hash)
+ template<typename ForwardKey>
+ std::optional<Value> pop_try__impl(const ForwardKey &key, uint64_t hash)
{
MAP_SLOT_PROBING_BEGIN (hash, slot) {
- if (slot.contains(key, m_is_equal, hash)) {
- Optional<Value> value = std::move(*slot.value());
+ if (slot.contains(key, is_equal_, hash)) {
+ std::optional<Value> value = std::move(*slot.value());
slot.remove();
- m_removed_slots++;
+ removed_slots_++;
return value;
}
if (slot.is_empty()) {
@@ -1086,13 +1024,13 @@ class Map {
}
template<typename ForwardKey, typename ForwardValue>
- Value pop_default__impl(const ForwardKey &key, ForwardValue &&default_value, uint32_t hash)
+ Value pop_default__impl(const ForwardKey &key, ForwardValue &&default_value, uint64_t hash)
{
MAP_SLOT_PROBING_BEGIN (hash, slot) {
- if (slot.contains(key, m_is_equal, hash)) {
+ if (slot.contains(key, is_equal_, hash)) {
Value value = std::move(*slot.value());
slot.remove();
- m_removed_slots++;
+ removed_slots_++;
return value;
}
if (slot.is_empty()) {
@@ -1106,23 +1044,23 @@ class Map {
auto add_or_modify__impl(ForwardKey &&key,
const CreateValueF &create_value,
const ModifyValueF &modify_value,
- uint32_t hash) -> decltype(create_value(nullptr))
+ uint64_t hash) -> decltype(create_value(nullptr))
{
using CreateReturnT = decltype(create_value(nullptr));
using ModifyReturnT = decltype(modify_value(nullptr));
- BLI_STATIC_ASSERT((std::is_same<CreateReturnT, ModifyReturnT>::value),
+ BLI_STATIC_ASSERT((std::is_same_v<CreateReturnT, ModifyReturnT>),
"Both callbacks should return the same type.");
this->ensure_can_add();
MAP_SLOT_PROBING_BEGIN (hash, slot) {
if (slot.is_empty()) {
- m_occupied_and_removed_slots++;
+ occupied_and_removed_slots_++;
slot.occupy_without_value(std::forward<ForwardKey>(key), hash);
Value *value_ptr = slot.value();
return create_value(value_ptr);
}
- if (slot.contains(key, m_is_equal, hash)) {
+ if (slot.contains(key, is_equal_, hash)) {
Value *value_ptr = slot.value();
return modify_value(value_ptr);
}
@@ -1131,17 +1069,17 @@ class Map {
}
template<typename ForwardKey, typename CreateValueF>
- Value &lookup_or_add_cb__impl(ForwardKey &&key, const CreateValueF &create_value, uint32_t hash)
+ Value &lookup_or_add_cb__impl(ForwardKey &&key, const CreateValueF &create_value, uint64_t hash)
{
this->ensure_can_add();
MAP_SLOT_PROBING_BEGIN (hash, slot) {
if (slot.is_empty()) {
slot.occupy(std::forward<ForwardKey>(key), create_value(), hash);
- m_occupied_and_removed_slots++;
+ occupied_and_removed_slots_++;
return *slot.value();
}
- if (slot.contains(key, m_is_equal, hash)) {
+ if (slot.contains(key, is_equal_, hash)) {
return *slot.value();
}
}
@@ -1149,17 +1087,17 @@ class Map {
}
template<typename ForwardKey, typename ForwardValue>
- Value &lookup_or_add__impl(ForwardKey &&key, ForwardValue &&value, uint32_t hash)
+ Value &lookup_or_add__impl(ForwardKey &&key, ForwardValue &&value, uint64_t hash)
{
this->ensure_can_add();
MAP_SLOT_PROBING_BEGIN (hash, slot) {
if (slot.is_empty()) {
slot.occupy(std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash);
- m_occupied_and_removed_slots++;
+ occupied_and_removed_slots_++;
return *slot.value();
}
- if (slot.contains(key, m_is_equal, hash)) {
+ if (slot.contains(key, is_equal_, hash)) {
return *slot.value();
}
}
@@ -1167,10 +1105,10 @@ class Map {
}
template<typename ForwardKey, typename ForwardValue>
- bool add_overwrite__impl(ForwardKey &&key, ForwardValue &&value, uint32_t hash)
+ bool add_overwrite__impl(ForwardKey &&key, ForwardValue &&value, uint64_t hash)
{
auto create_func = [&](Value *ptr) {
- new (ptr) Value(std::forward<ForwardValue>(value));
+ new ((void *)ptr) Value(std::forward<ForwardValue>(value));
return true;
};
auto modify_func = [&](Value *ptr) {
@@ -1182,13 +1120,13 @@ class Map {
}
template<typename ForwardKey>
- const Value *lookup_ptr__impl(const ForwardKey &key, uint32_t hash) const
+ const Value *lookup_ptr__impl(const ForwardKey &key, uint64_t hash) const
{
MAP_SLOT_PROBING_BEGIN (hash, slot) {
if (slot.is_empty()) {
return nullptr;
}
- if (slot.contains(key, m_is_equal, hash)) {
+ if (slot.contains(key, is_equal_, hash)) {
return slot.value();
}
}
@@ -1196,12 +1134,12 @@ class Map {
}
template<typename ForwardKey>
- uint32_t count_collisions__impl(const ForwardKey &key, uint32_t hash) const
+ int64_t count_collisions__impl(const ForwardKey &key, uint64_t hash) const
{
- uint32_t collisions = 0;
+ int64_t collisions = 0;
MAP_SLOT_PROBING_BEGIN (hash, slot) {
- if (slot.contains(key, m_is_equal, hash)) {
+ if (slot.contains(key, is_equal_, hash)) {
return collisions;
}
if (slot.is_empty()) {
@@ -1214,73 +1152,88 @@ class Map {
void ensure_can_add()
{
- if (m_occupied_and_removed_slots >= m_usable_slots) {
+ if (occupied_and_removed_slots_ >= usable_slots_) {
this->realloc_and_reinsert(this->size() + 1);
- BLI_assert(m_occupied_and_removed_slots < m_usable_slots);
+ BLI_assert(occupied_and_removed_slots_ < usable_slots_);
}
}
};
/**
+ * Same as a normal Map, but does not use Blender's guarded allocator. This is useful when
+ * allocating memory with static storage duration.
+ */
+template<typename Key,
+ typename Value,
+ int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(Key) +
+ sizeof(Value)),
+ typename ProbingStrategy = DefaultProbingStrategy,
+ typename Hash = DefaultHash<Key>,
+ typename IsEqual = DefaultEquality,
+ typename Slot = typename DefaultMapSlot<Key, Value>::type>
+using RawMap =
+ Map<Key, Value, InlineBufferCapacity, ProbingStrategy, Hash, IsEqual, Slot, RawAllocator>;
+
+/**
* A wrapper for std::unordered_map with the API of blender::Map. This can be used for
* benchmarking.
*/
template<typename Key, typename Value> class StdUnorderedMapWrapper {
private:
using MapType = std::unordered_map<Key, Value, blender::DefaultHash<Key>>;
- MapType m_map;
+ MapType map_;
public:
- uint32_t size() const
+ int64_t size() const
{
- return (uint32_t)m_map.size();
+ return (int64_t)map_.size();
}
bool is_empty() const
{
- return m_map.empty();
+ return map_.empty();
}
- void reserve(uint32_t n)
+ void reserve(int64_t n)
{
- m_map.reserve(n);
+ map_.reserve(n);
}
template<typename ForwardKey, typename ForwardValue>
void add_new(ForwardKey &&key, ForwardValue &&value)
{
- m_map.insert({std::forward<ForwardKey>(key), std::forward<ForwardValue>(value)});
+ map_.insert({std::forward<ForwardKey>(key), std::forward<ForwardValue>(value)});
}
template<typename ForwardKey, typename ForwardValue>
bool add(ForwardKey &&key, ForwardValue &&value)
{
- return m_map.insert({std::forward<ForwardKey>(key), std::forward<ForwardValue>(value)}).second;
+ return map_.insert({std::forward<ForwardKey>(key), std::forward<ForwardValue>(value)}).second;
}
bool contains(const Key &key) const
{
- return m_map.find(key) != m_map.end();
+ return map_.find(key) != map_.end();
}
bool remove(const Key &key)
{
- return (bool)m_map.erase(key);
+ return (bool)map_.erase(key);
}
Value &lookup(const Key &key)
{
- return m_map.find(key)->second;
+ return map_.find(key)->second;
}
const Value &lookup(const Key &key) const
{
- return m_map.find(key)->second;
+ return map_.find(key)->second;
}
void clear()
{
- m_map.clear();
+ map_.clear();
}
void print_stats(StringRef UNUSED(name) = "") const