diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 0bd7a20e..419d7d5e 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -3021,44 +3021,30 @@ struct table : boost::unordered::detail::functionsnext_ != end); - - std::size_t count = 0; - - node_pointer n = next_node(prev); - prev->next_ = end; - do { - node_pointer next = next_node(n); - destroy_node(n); - n = next; - ++count; - } while (n != end); - - size_ -= count; - return count; - } - void delete_buckets() { if (buckets_) { - if (size_) - delete_nodes(get_previous_start(), node_pointer()); + node_pointer n = + static_cast(get_bucket(bucket_count_)->next_); if (bucket::extra_node) { - node_pointer n = - static_cast(get_bucket(bucket_count_)->next_); + node_pointer next = next_node(n); boost::unordered::detail::func::destroy(boost::addressof(*n)); node_allocator_traits::deallocate(node_alloc(), n, 1); + n = next; + } + + while (n) { + node_pointer next = next_node(n); + destroy_node(n); + n = next; } destroy_buckets(); buckets_ = bucket_pointer(); max_load_ = 0; + size_ = 0; } - - BOOST_ASSERT(!size_); } void destroy_buckets() @@ -3104,6 +3090,11 @@ struct table : boost::unordered::detail::functionsfind_previous_node(k, bucket_index); if (!prev) return 0; - node_pointer end = next_node(next_node(prev)); - this->delete_nodes(prev, end); - this->fix_bucket(bucket_index, prev, end); + node_pointer n = next_node(prev); + node_pointer n2 = next_node(n); + prev->next_ = n2; + --size_; + this->fix_bucket(bucket_index, prev, n2); + this->destroy_node(n); return 1; } @@ -4082,11 +4076,17 @@ struct table : boost::unordered::detail::functionsdelete_nodes(prev, end); - this->fix_bucket(bucket_index, prev, end); + std::size_t deleted_count = 0; + node_pointer n = next_node(prev); + do { + node_pointer n2 = next_node(n); + destroy_node(n); + ++deleted_count; + n = n2; + } while (n && !n->is_first_in_group()); + size_ -= deleted_count; + prev->next_ = n; + this->fix_bucket(bucket_index, prev, n); return deleted_count; } @@ -4191,6 +4191,30 @@ struct table : boost::unordered::detail::functions inline void table::clear_impl() +{ + if (size_) { + bucket_pointer end = get_bucket(bucket_count_); + for (bucket_pointer it = buckets_; it != end; ++it) { + it->next_ = node_pointer(); + } + + link_pointer prev = end->first_from_start(); + node_pointer n = next_node(prev); + prev->next_ = node_pointer(); + size_ = 0; + + while (n) { + node_pointer next = next_node(n); + destroy_node(n); + n = next; + } + } +} + //////////////////////////////////////////////////////////////////////////// // Reserve & Rehash @@ -4275,7 +4299,14 @@ inline void table::rehash_impl(std::size_t num_buckets) } BOOST_CATCH(...) { - delete_nodes(prev, node_pointer()); + node_pointer n = next_node(prev); + prev->next_ = node_pointer(); + while (n) { + node_pointer next = next_node(n); + destroy_node(n); + --size_; + n = next; + } BOOST_RETHROW } BOOST_CATCH_END diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index 134d31a8..a5d3ffa2 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -728,7 +728,7 @@ template class unordered_map // value_allocator_traits::is_always_equal::value && // is_nothrow_move_assignable_v && // is_nothrow_move_assignable_v

) - void clear() BOOST_NOEXCEPT; + void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template void merge(boost::unordered_map& source); @@ -1263,7 +1263,7 @@ template class unordered_multimap // value_allocator_traits::is_always_equal::value && // is_nothrow_move_assignable_v && // is_nothrow_move_assignable_v

) - void clear() BOOST_NOEXCEPT; + void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template void merge(boost::unordered_multimap& source); @@ -1611,15 +1611,6 @@ void unordered_map::swap(unordered_map& other) table_.swap(other.table_); } -template -void unordered_map::clear() BOOST_NOEXCEPT -{ - if (table_.size_) { - table_.clear_buckets(); - table_.delete_nodes(table_.get_previous_start(), node_pointer()); - } -} - template template void unordered_map::merge( @@ -2096,15 +2087,6 @@ void unordered_multimap::swap(unordered_multimap& other) table_.swap(other.table_); } -template -void unordered_multimap::clear() BOOST_NOEXCEPT -{ - if (table_.size_) { - table_.clear_buckets(); - table_.delete_nodes(table_.get_previous_start(), node_pointer()); - } -} - // observers template diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index 58ea6417..b160c76e 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -447,7 +447,7 @@ template class unordered_set // value_allocator_traits::is_always_equal::value && // is_nothrow_move_assignable_v && // is_nothrow_move_assignable_v

) - void clear() BOOST_NOEXCEPT; + void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template void merge(boost::unordered_set& source); @@ -950,7 +950,7 @@ template class unordered_multiset // value_allocator_traits::is_always_equal::value && // is_nothrow_move_assignable_v && // is_nothrow_move_assignable_v

) - void clear() BOOST_NOEXCEPT; + void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template void merge(boost::unordered_multiset& source); @@ -1275,15 +1275,6 @@ void unordered_set::swap(unordered_set& other) table_.swap(other.table_); } -template -void unordered_set::clear() BOOST_NOEXCEPT -{ - if (table_.size_) { - table_.clear_buckets(); - table_.delete_nodes(table_.get_previous_start(), node_pointer()); - } -} - // observers template @@ -1679,15 +1670,6 @@ void unordered_multiset::swap(unordered_multiset& other) table_.swap(other.table_); } -template -void unordered_multiset::clear() BOOST_NOEXCEPT -{ - if (table_.size_) { - table_.clear_buckets(); - table_.delete_nodes(table_.get_previous_start(), node_pointer()); - } -} - // observers template