From 27c00ae4982e8298f511b3f623ee0f48e9b9ee35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sat, 25 Jun 2022 18:32:27 +0200 Subject: [PATCH] Fixes #75 ("Bug: Rehashing an empty unordered_set with cache_begin set to true hits an assert") --- include/boost/intrusive/hashtable.hpp | 20 +++++++++++++------- test/unordered_test.hpp | 8 ++++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp index 2cc54c1..b8bc877 100644 --- a/include/boost/intrusive/hashtable.hpp +++ b/include/boost/intrusive/hashtable.hpp @@ -1546,6 +1546,9 @@ struct bucket_hash_equal_t BOOST_INTRUSIVE_FORCEINLINE void priv_set_cache(bucket_ptr) {} + BOOST_INTRUSIVE_FORCEINLINE void priv_set_cache_bucket_num(std::size_t) + {} + BOOST_INTRUSIVE_FORCEINLINE std::size_t priv_get_cache_bucket_num() { return 0u; } @@ -1638,6 +1641,12 @@ struct bucket_hash_equal_tpriv_usable_bucket_count()); + this->cached_begin_ = this->priv_bucket_pointer() + std::ptrdiff_t(insertion_bucket); + } + BOOST_INTRUSIVE_FORCEINLINE std::size_t priv_get_cache_bucket_num() { return std::size_t(this->cached_begin_ - this->priv_bucket_pointer()); } @@ -3602,9 +3611,8 @@ class hashtable_impl slist_node_ptr old_bucket_node_ptr = old_buckets[difference_type(n)].get_node_ptr(); slist_node_algorithms::transfer_after(new_bucket_nodeptr, old_bucket_node_ptr); } - //Put cache to safe position - this->priv_init_cache(); - this->priv_insertion_update_cache(ini_n); + //Reset cache to safe position + this->priv_set_cache_bucket_num(ini_n); } this->priv_set_sentinel_bucket(); @@ -3759,7 +3767,6 @@ class hashtable_impl this->priv_size_traits().set_size(0); //Put cache to safe position this->priv_init_cache(); - this->priv_insertion_update_cache(size_type(0u)); this->priv_unset_sentinel_bucket(); const size_type split = this->rehash_split_from_bucket_count(new_bucket_count); @@ -3824,8 +3831,7 @@ class hashtable_impl if(&new_bucket_traits != &this->priv_bucket_traits()) this->priv_bucket_traits() = new_bucket_traits; this->priv_set_sentinel_bucket(); - this->priv_init_cache(); - this->priv_insertion_update_cache(new_first_bucket_num); + this->priv_set_cache_bucket_num(new_first_bucket_num); rollback1.release(); rollback2.release(); } @@ -3923,7 +3929,7 @@ class hashtable_impl rollback.release(); this->priv_size_traits().set_size(src.priv_size_traits().get_size()); this->priv_split_traits().set_size(dst_bucket_count); - this->priv_insertion_update_cache(0u); + this->priv_set_cache_bucket_num(0u); this->priv_erasure_update_cache(); } diff --git a/test/unordered_test.hpp b/test/unordered_test.hpp index e5c91c0..33a6679 100644 --- a/test/unordered_test.hpp +++ b/test/unordered_test.hpp @@ -635,6 +635,14 @@ void test_unordered::test_rehash(value_cont_type& values, deta testset1.full_rehash(); { int init_values [] = { 1, 2, 2, 3, 4, 5 }; TEST_INTRUSIVE_SEQUENCE_MAYBEUNIQUE( init_values, testset1 ); } + + //Test empty rehash + testset1.clear(); + testset1.rehash(bucket_traits( + pointer_traits::pointer_to(buckets1[0]), sizeof(buckets1) / sizeof(*buckets1))); + BOOST_TEST(testset1.empty()); + testset1.full_rehash(); + BOOST_TEST(testset1.empty()); } //test: find, equal_range (lower_bound, upper_bound):