From b032ba2f569b2d8aad11e70e6aa670fa81f104fe Mon Sep 17 00:00:00 2001 From: halx99 Date: Tue, 10 Jan 2023 22:16:38 +0800 Subject: [PATCH] Update robin_map to v1.2.1 --- thirdparty/README.md | 2 +- .../include/tsl/robin_growth_policy.h | 6 +-- thirdparty/robin-map/include/tsl/robin_hash.h | 44 ++++++++++++++----- thirdparty/robin-map/include/tsl/robin_map.h | 12 ++--- 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/thirdparty/README.md b/thirdparty/README.md index cb2e10162a..eea743649c 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -196,7 +196,7 @@ ## 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` - Forward `robin_map::operator[]` key by `std::forward` same with `stl map/unordered_map` - License: MIT diff --git a/thirdparty/robin-map/include/tsl/robin_growth_policy.h b/thirdparty/robin-map/include/tsl/robin_growth_policy.h index fa576a954a..1a22d895fc 100644 --- a/thirdparty/robin-map/include/tsl/robin_growth_policy.h +++ b/thirdparty/robin-map/include/tsl/robin_growth_policy.h @@ -51,15 +51,15 @@ #define TSL_RH_THROW_OR_TERMINATE(ex, msg) throw ex(msg) #else #define TSL_RH_NO_EXCEPTIONS -#ifdef NDEBUG -#define TSL_RH_THROW_OR_TERMINATE(ex, msg) std::terminate() -#else +#ifdef TSL_DEBUG #include #define TSL_RH_THROW_OR_TERMINATE(ex, msg) \ do { \ std::cerr << msg << std::endl; \ std::terminate(); \ } while (0) +#else +#define TSL_RH_THROW_OR_TERMINATE(ex, msg) std::terminate() #endif #endif diff --git a/thirdparty/robin-map/include/tsl/robin_hash.h b/thirdparty/robin-map/include/tsl/robin_hash.h index f8b6144c6f..29b03569bd 100644 --- a/thirdparty/robin-map/include/tsl/robin_hash.h +++ b/thirdparty/robin-map/include/tsl/robin_hash.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -195,6 +196,7 @@ class bucket_entry : public bucket_entry_hash { value_type(other.value()); 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 { value_type(std::move(other.value())); 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( @@ -249,12 +252,22 @@ class bucket_entry : public bucket_entry_hash { value_type& value() noexcept { tsl_rh_assert(!empty()); +#if defined(__cplusplus) && __cplusplus >= 201703L + return *std::launder( + reinterpret_cast(std::addressof(m_value))); +#else return *reinterpret_cast(std::addressof(m_value)); +#endif } const value_type& value() const noexcept { tsl_rh_assert(!empty()); +#if defined(__cplusplus) && __cplusplus >= 201703L + return *std::launder( + reinterpret_cast(std::addressof(m_value))); +#else return *reinterpret_cast(std::addressof(m_value)); +#endif } distance_type dist_from_ideal_bucket() const noexcept { @@ -283,6 +296,7 @@ class bucket_entry : public bucket_entry_hash { void swap_with_value_in_bucket(distance_type& dist_from_ideal_bucket, truncated_hash_type& hash, value_type& value) { tsl_rh_assert(!empty()); + tsl_rh_assert(dist_from_ideal_bucket > m_dist_from_ideal_bucket); using std::swap; swap(value, this->value()); @@ -310,19 +324,16 @@ class bucket_entry : public bucket_entry_hash { public: 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 <= (std::numeric_limits::max)() - 1, "DIST_FROM_IDEAL_BUCKET_LIMIT must be <= " "std::numeric_limits::max() - 1."); private: - using storage = typename std::aligned_storage::type; - distance_type m_dist_from_ideal_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 = tsl::detail_robin_hash::bucket_entry; using distance_type = typename bucket_entry::distance_type; - using buckets_allocator = typename std::allocator_traits::template rebind_alloc; + using buckets_allocator = typename std::allocator_traits< + allocator_type>::template rebind_alloc; using buckets_container_type = std::vector; + public: /** * The 'operator*()' and 'operator->()' methods return a const reference and * const pointer respectively to the stored value type. @@ -716,7 +728,7 @@ public: robin_hash& operator=(robin_hash&& other) { other.swap(*this); - other.clear(); + other.clear_and_shrink(); return *this; } @@ -1125,6 +1137,7 @@ public: m_max_load_factor = clamp(ml, float(MINIMUM_MAX_LOAD_FACTOR), float(MAXIMUM_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_) { @@ -1276,7 +1289,7 @@ public: dist_from_ideal_bucket++; } - if (rehash_on_extreme_load()) { + while (rehash_on_extreme_load(dist_from_ideal_bucket)) { ibucket = bucket_for_hash(hash); dist_from_ideal_bucket = 0; @@ -1328,6 +1341,8 @@ public: void insert_value_impl(std::size_t ibucket, distance_type dist_from_ideal_bucket, 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, value); ibucket = next_bucket(ibucket); @@ -1336,7 +1351,7 @@ public: while (!m_buckets[ibucket].empty()) { if (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) { /** * 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(*this), static_cast(*this), get_allocator(), m_min_load_factor, m_max_load_factor); + tsl_rh_assert(size() <= new_table.m_load_threshold); const bool use_stored_hash = USE_STORED_HASH_ON_REHASH(new_table.bucket_count()); @@ -1421,8 +1437,11 @@ public: * * Return true if the table has been rehashed. */ - bool rehash_on_extreme_load() { - if (m_grow_on_next_insert || size() >= m_load_threshold) { + bool rehash_on_extreme_load(distance_type curr_dist_from_ideal_bucket) { + 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()); m_grow_on_next_insert = false; @@ -1628,6 +1647,7 @@ public: */ bucket_entry* static_empty_bucket_ptr() noexcept { static bucket_entry empty_bucket(true); + tsl_rh_assert(empty_bucket.empty()); return &empty_bucket; } diff --git a/thirdparty/robin-map/include/tsl/robin_map.h b/thirdparty/robin-map/include/tsl/robin_map.h index b6c1577c0c..95a8a98301 100644 --- a/thirdparty/robin-map/include/tsl/robin_map.h +++ b/thirdparty/robin-map/include/tsl/robin_map.h @@ -97,8 +97,8 @@ class robin_map { public: using key_type = Key; - const key_type& operator()(const std::pair& key_value) const - noexcept { + const key_type& operator()( + const std::pair& key_value) const noexcept { return key_value.first; } @@ -111,8 +111,8 @@ class robin_map { public: using value_type = T; - const value_type& operator()(const std::pair& key_value) const - noexcept { + const value_type& operator()( + const std::pair& key_value) const noexcept { return key_value.second; } @@ -120,7 +120,9 @@ class robin_map { return key_value.second; } - value_type& operator()(std::pair& key_value) noexcept { return key_value.second; } + value_type& operator()(std::pair& key_value) noexcept { + return key_value.second; + } }; using ht = detail_robin_hash::robin_hash, std::pair, KeySelect,