mirror of https://github.com/axmolengine/axmol.git
Update robin_map to v1.2.1
This commit is contained in:
parent
100a688ce5
commit
b032ba2f56
|
@ -196,7 +196,7 @@
|
||||||
|
|
||||||
## robin-map
|
## robin-map
|
||||||
- [![Upstream](https://img.shields.io/github/v/tag/Tessil/robin-map?label=Upstream)](https://github.com/Tessil/robin-map)
|
- [![Upstream](https://img.shields.io/github/v/tag/Tessil/robin-map?label=Upstream)](https://github.com/Tessil/robin-map)
|
||||||
- Version: 1.0.1 with modified for more compatible with stl
|
- Version: 1.2.1 with modified for more compatible with stl
|
||||||
- Modify `robin_map::iterator->second` to mutable same with `stl map/unordered_map`
|
- Modify `robin_map::iterator->second` to mutable same with `stl map/unordered_map`
|
||||||
- Forward `robin_map::operator[]` key by `std::forward` same with `stl map/unordered_map`
|
- Forward `robin_map::operator[]` key by `std::forward` same with `stl map/unordered_map`
|
||||||
- License: MIT
|
- License: MIT
|
||||||
|
|
|
@ -51,15 +51,15 @@
|
||||||
#define TSL_RH_THROW_OR_TERMINATE(ex, msg) throw ex(msg)
|
#define TSL_RH_THROW_OR_TERMINATE(ex, msg) throw ex(msg)
|
||||||
#else
|
#else
|
||||||
#define TSL_RH_NO_EXCEPTIONS
|
#define TSL_RH_NO_EXCEPTIONS
|
||||||
#ifdef NDEBUG
|
#ifdef TSL_DEBUG
|
||||||
#define TSL_RH_THROW_OR_TERMINATE(ex, msg) std::terminate()
|
|
||||||
#else
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#define TSL_RH_THROW_OR_TERMINATE(ex, msg) \
|
#define TSL_RH_THROW_OR_TERMINATE(ex, msg) \
|
||||||
do { \
|
do { \
|
||||||
std::cerr << msg << std::endl; \
|
std::cerr << msg << std::endl; \
|
||||||
std::terminate(); \
|
std::terminate(); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define TSL_RH_THROW_OR_TERMINATE(ex, msg) std::terminate()
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <new>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
@ -195,6 +196,7 @@ class bucket_entry : public bucket_entry_hash<StoreHash> {
|
||||||
value_type(other.value());
|
value_type(other.value());
|
||||||
m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket;
|
m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket;
|
||||||
}
|
}
|
||||||
|
tsl_rh_assert(empty() == other.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -212,6 +214,7 @@ class bucket_entry : public bucket_entry_hash<StoreHash> {
|
||||||
value_type(std::move(other.value()));
|
value_type(std::move(other.value()));
|
||||||
m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket;
|
m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket;
|
||||||
}
|
}
|
||||||
|
tsl_rh_assert(empty() == other.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
bucket_entry& operator=(const bucket_entry& other) noexcept(
|
bucket_entry& operator=(const bucket_entry& other) noexcept(
|
||||||
|
@ -249,12 +252,22 @@ class bucket_entry : public bucket_entry_hash<StoreHash> {
|
||||||
|
|
||||||
value_type& value() noexcept {
|
value_type& value() noexcept {
|
||||||
tsl_rh_assert(!empty());
|
tsl_rh_assert(!empty());
|
||||||
|
#if defined(__cplusplus) && __cplusplus >= 201703L
|
||||||
|
return *std::launder(
|
||||||
|
reinterpret_cast<value_type*>(std::addressof(m_value)));
|
||||||
|
#else
|
||||||
return *reinterpret_cast<value_type*>(std::addressof(m_value));
|
return *reinterpret_cast<value_type*>(std::addressof(m_value));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const value_type& value() const noexcept {
|
const value_type& value() const noexcept {
|
||||||
tsl_rh_assert(!empty());
|
tsl_rh_assert(!empty());
|
||||||
|
#if defined(__cplusplus) && __cplusplus >= 201703L
|
||||||
|
return *std::launder(
|
||||||
|
reinterpret_cast<const value_type*>(std::addressof(m_value)));
|
||||||
|
#else
|
||||||
return *reinterpret_cast<const value_type*>(std::addressof(m_value));
|
return *reinterpret_cast<const value_type*>(std::addressof(m_value));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
distance_type dist_from_ideal_bucket() const noexcept {
|
distance_type dist_from_ideal_bucket() const noexcept {
|
||||||
|
@ -283,6 +296,7 @@ class bucket_entry : public bucket_entry_hash<StoreHash> {
|
||||||
void swap_with_value_in_bucket(distance_type& dist_from_ideal_bucket,
|
void swap_with_value_in_bucket(distance_type& dist_from_ideal_bucket,
|
||||||
truncated_hash_type& hash, value_type& value) {
|
truncated_hash_type& hash, value_type& value) {
|
||||||
tsl_rh_assert(!empty());
|
tsl_rh_assert(!empty());
|
||||||
|
tsl_rh_assert(dist_from_ideal_bucket > m_dist_from_ideal_bucket);
|
||||||
|
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(value, this->value());
|
swap(value, this->value());
|
||||||
|
@ -310,19 +324,16 @@ class bucket_entry : public bucket_entry_hash<StoreHash> {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const distance_type EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET = -1;
|
static const distance_type EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET = -1;
|
||||||
static const distance_type DIST_FROM_IDEAL_BUCKET_LIMIT = 4096;
|
static const distance_type DIST_FROM_IDEAL_BUCKET_LIMIT = 8192;
|
||||||
static_assert(DIST_FROM_IDEAL_BUCKET_LIMIT <=
|
static_assert(DIST_FROM_IDEAL_BUCKET_LIMIT <=
|
||||||
(std::numeric_limits<distance_type>::max)() - 1,
|
(std::numeric_limits<distance_type>::max)() - 1,
|
||||||
"DIST_FROM_IDEAL_BUCKET_LIMIT must be <= "
|
"DIST_FROM_IDEAL_BUCKET_LIMIT must be <= "
|
||||||
"std::numeric_limits<distance_type>::max() - 1.");
|
"std::numeric_limits<distance_type>::max() - 1.");
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using storage = typename std::aligned_storage<sizeof(value_type),
|
|
||||||
alignof(value_type)>::type;
|
|
||||||
|
|
||||||
distance_type m_dist_from_ideal_bucket;
|
distance_type m_dist_from_ideal_bucket;
|
||||||
bool m_last_bucket;
|
bool m_last_bucket;
|
||||||
storage m_value;
|
alignas(value_type) unsigned char m_value[sizeof(value_type)];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -415,14 +426,15 @@ class robin_hash : private Hash, private KeyEqual, private GrowthPolicy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
using bucket_entry =
|
using bucket_entry =
|
||||||
tsl::detail_robin_hash::bucket_entry<value_type, STORE_HASH>;
|
tsl::detail_robin_hash::bucket_entry<value_type, STORE_HASH>;
|
||||||
using distance_type = typename bucket_entry::distance_type;
|
using distance_type = typename bucket_entry::distance_type;
|
||||||
|
|
||||||
using buckets_allocator = typename std::allocator_traits<allocator_type>::template rebind_alloc<bucket_entry>;
|
using buckets_allocator = typename std::allocator_traits<
|
||||||
|
allocator_type>::template rebind_alloc<bucket_entry>;
|
||||||
using buckets_container_type = std::vector<bucket_entry, buckets_allocator>;
|
using buckets_container_type = std::vector<bucket_entry, buckets_allocator>;
|
||||||
|
|
||||||
|
public:
|
||||||
/**
|
/**
|
||||||
* The 'operator*()' and 'operator->()' methods return a const reference and
|
* The 'operator*()' and 'operator->()' methods return a const reference and
|
||||||
* const pointer respectively to the stored value type.
|
* const pointer respectively to the stored value type.
|
||||||
|
@ -716,7 +728,7 @@ public:
|
||||||
|
|
||||||
robin_hash& operator=(robin_hash&& other) {
|
robin_hash& operator=(robin_hash&& other) {
|
||||||
other.swap(*this);
|
other.swap(*this);
|
||||||
other.clear();
|
other.clear_and_shrink();
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -1125,6 +1137,7 @@ public:
|
||||||
m_max_load_factor = clamp(ml, float(MINIMUM_MAX_LOAD_FACTOR),
|
m_max_load_factor = clamp(ml, float(MINIMUM_MAX_LOAD_FACTOR),
|
||||||
float(MAXIMUM_MAX_LOAD_FACTOR));
|
float(MAXIMUM_MAX_LOAD_FACTOR));
|
||||||
m_load_threshold = size_type(float(bucket_count()) * m_max_load_factor);
|
m_load_threshold = size_type(float(bucket_count()) * m_max_load_factor);
|
||||||
|
tsl_rh_assert(bucket_count() == 0 || m_load_threshold < bucket_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
void rehash(size_type count_) {
|
void rehash(size_type count_) {
|
||||||
|
@ -1276,7 +1289,7 @@ public:
|
||||||
dist_from_ideal_bucket++;
|
dist_from_ideal_bucket++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rehash_on_extreme_load()) {
|
while (rehash_on_extreme_load(dist_from_ideal_bucket)) {
|
||||||
ibucket = bucket_for_hash(hash);
|
ibucket = bucket_for_hash(hash);
|
||||||
dist_from_ideal_bucket = 0;
|
dist_from_ideal_bucket = 0;
|
||||||
|
|
||||||
|
@ -1328,6 +1341,8 @@ public:
|
||||||
void insert_value_impl(std::size_t ibucket,
|
void insert_value_impl(std::size_t ibucket,
|
||||||
distance_type dist_from_ideal_bucket,
|
distance_type dist_from_ideal_bucket,
|
||||||
truncated_hash_type hash, value_type& value) {
|
truncated_hash_type hash, value_type& value) {
|
||||||
|
tsl_rh_assert(dist_from_ideal_bucket >
|
||||||
|
m_buckets[ibucket].dist_from_ideal_bucket());
|
||||||
m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, hash,
|
m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, hash,
|
||||||
value);
|
value);
|
||||||
ibucket = next_bucket(ibucket);
|
ibucket = next_bucket(ibucket);
|
||||||
|
@ -1336,7 +1351,7 @@ public:
|
||||||
while (!m_buckets[ibucket].empty()) {
|
while (!m_buckets[ibucket].empty()) {
|
||||||
if (dist_from_ideal_bucket >
|
if (dist_from_ideal_bucket >
|
||||||
m_buckets[ibucket].dist_from_ideal_bucket()) {
|
m_buckets[ibucket].dist_from_ideal_bucket()) {
|
||||||
if (dist_from_ideal_bucket >=
|
if (dist_from_ideal_bucket >
|
||||||
bucket_entry::DIST_FROM_IDEAL_BUCKET_LIMIT) {
|
bucket_entry::DIST_FROM_IDEAL_BUCKET_LIMIT) {
|
||||||
/**
|
/**
|
||||||
* The number of probes is really high, rehash the map on the next
|
* The number of probes is really high, rehash the map on the next
|
||||||
|
@ -1361,6 +1376,7 @@ public:
|
||||||
robin_hash new_table(count_, static_cast<Hash&>(*this),
|
robin_hash new_table(count_, static_cast<Hash&>(*this),
|
||||||
static_cast<KeyEqual&>(*this), get_allocator(),
|
static_cast<KeyEqual&>(*this), get_allocator(),
|
||||||
m_min_load_factor, m_max_load_factor);
|
m_min_load_factor, m_max_load_factor);
|
||||||
|
tsl_rh_assert(size() <= new_table.m_load_threshold);
|
||||||
|
|
||||||
const bool use_stored_hash =
|
const bool use_stored_hash =
|
||||||
USE_STORED_HASH_ON_REHASH(new_table.bucket_count());
|
USE_STORED_HASH_ON_REHASH(new_table.bucket_count());
|
||||||
|
@ -1421,8 +1437,11 @@ public:
|
||||||
*
|
*
|
||||||
* Return true if the table has been rehashed.
|
* Return true if the table has been rehashed.
|
||||||
*/
|
*/
|
||||||
bool rehash_on_extreme_load() {
|
bool rehash_on_extreme_load(distance_type curr_dist_from_ideal_bucket) {
|
||||||
if (m_grow_on_next_insert || size() >= m_load_threshold) {
|
if (m_grow_on_next_insert ||
|
||||||
|
curr_dist_from_ideal_bucket >
|
||||||
|
bucket_entry::DIST_FROM_IDEAL_BUCKET_LIMIT ||
|
||||||
|
size() >= m_load_threshold) {
|
||||||
rehash_impl(GrowthPolicy::next_bucket_count());
|
rehash_impl(GrowthPolicy::next_bucket_count());
|
||||||
m_grow_on_next_insert = false;
|
m_grow_on_next_insert = false;
|
||||||
|
|
||||||
|
@ -1628,6 +1647,7 @@ public:
|
||||||
*/
|
*/
|
||||||
bucket_entry* static_empty_bucket_ptr() noexcept {
|
bucket_entry* static_empty_bucket_ptr() noexcept {
|
||||||
static bucket_entry empty_bucket(true);
|
static bucket_entry empty_bucket(true);
|
||||||
|
tsl_rh_assert(empty_bucket.empty());
|
||||||
return &empty_bucket;
|
return &empty_bucket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,8 +97,8 @@ class robin_map {
|
||||||
public:
|
public:
|
||||||
using key_type = Key;
|
using key_type = Key;
|
||||||
|
|
||||||
const key_type& operator()(const std::pair<Key, T>& key_value) const
|
const key_type& operator()(
|
||||||
noexcept {
|
const std::pair<Key, T>& key_value) const noexcept {
|
||||||
return key_value.first;
|
return key_value.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,8 +111,8 @@ class robin_map {
|
||||||
public:
|
public:
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
|
|
||||||
const value_type& operator()(const std::pair<Key, T>& key_value) const
|
const value_type& operator()(
|
||||||
noexcept {
|
const std::pair<Key, T>& key_value) const noexcept {
|
||||||
return key_value.second;
|
return key_value.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,9 @@ class robin_map {
|
||||||
return key_value.second;
|
return key_value.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_type& operator()(std::pair<const Key, T>& key_value) noexcept { return key_value.second; }
|
value_type& operator()(std::pair<const Key, T>& key_value) noexcept {
|
||||||
|
return key_value.second;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using ht = detail_robin_hash::robin_hash<std::pair<Key, T>, std::pair<const Key, T>, KeySelect,
|
using ht = detail_robin_hash::robin_hash<std::pair<Key, T>, std::pair<const Key, T>, KeySelect,
|
||||||
|
|
Loading…
Reference in New Issue