Update robin_map to v1.2.1

This commit is contained in:
halx99 2023-01-10 22:16:38 +08:00
parent 100a688ce5
commit b032ba2f56
4 changed files with 43 additions and 21 deletions

View File

@ -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

View File

@ -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 <iostream>
#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

View File

@ -33,6 +33,7 @@
#include <iterator>
#include <limits>
#include <memory>
#include <new>
#include <stdexcept>
#include <tuple>
#include <type_traits>
@ -195,6 +196,7 @@ class bucket_entry : public bucket_entry_hash<StoreHash> {
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<StoreHash> {
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<StoreHash> {
value_type& value() noexcept {
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));
#endif
}
const value_type& value() const noexcept {
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));
#endif
}
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,
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<StoreHash> {
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<distance_type>::max)() - 1,
"DIST_FROM_IDEAL_BUCKET_LIMIT must be <= "
"std::numeric_limits<distance_type>::max() - 1.");
private:
using storage = typename std::aligned_storage<sizeof(value_type),
alignof(value_type)>::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<value_type, STORE_HASH>;
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>;
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<Hash&>(*this),
static_cast<KeyEqual&>(*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;
}

View File

@ -97,8 +97,8 @@ class robin_map {
public:
using key_type = Key;
const key_type& operator()(const std::pair<Key, T>& key_value) const
noexcept {
const key_type& operator()(
const std::pair<Key, T>& 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, T>& key_value) const
noexcept {
const value_type& operator()(
const std::pair<Key, T>& key_value) const noexcept {
return key_value.second;
}
@ -120,7 +120,9 @@ class robin_map {
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,