Cleaner create_buckets implementation

This commit is contained in:
Daniel James
2017-04-30 10:41:22 +01:00
parent 899248acbf
commit c75b332240

View File

@ -2898,57 +2898,37 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
// Strong exception safety. // Strong exception safety.
void create_buckets(std::size_t new_count) void create_buckets(std::size_t new_count)
{ {
std::size_t length = new_count + 1; link_pointer dummy_node;
bucket_pointer new_buckets =
bucket_allocator_traits::allocate(bucket_alloc(), length);
bucket_pointer constructed = new_buckets;
// TODO: Apart from constructing the dummy node this is now // Construct the new buckets and dummy node, and destroy the old buckets
// nothrow, so maybe rearrange it a bit so that less if (buckets_) {
// exception handling is required. dummy_node =
BOOST_TRY (buckets_ + static_cast<std::ptrdiff_t>(bucket_count_))->next_;
{ bucket_pointer new_buckets = bucket_allocator_traits::allocate(
bucket_pointer end = bucket_alloc(), new_count + 1);
new_buckets + static_cast<std::ptrdiff_t>(new_count); destroy_buckets();
for (; constructed != end; ++constructed) { buckets_ = new_buckets;
new (boost::addressof(*constructed)) bucket(); } else if (bucket::extra_node) {
} node_constructor a(node_alloc());
a.create_node();
if (buckets_) { buckets_ = bucket_allocator_traits::allocate(
// Copy the nodes to the new buckets, including the dummy bucket_alloc(), new_count + 1);
// node if there is one. dummy_node = a.release();
new (boost::addressof(*constructed)) bucket( } else {
(buckets_ + static_cast<std::ptrdiff_t>(bucket_count_)) dummy_node = link_pointer();
->next_); buckets_ = bucket_allocator_traits::allocate(
++constructed; bucket_alloc(), new_count + 1);
destroy_buckets();
} else if (bucket::extra_node) {
node_constructor a(node_alloc());
a.create_node();
new (boost::addressof(*constructed)) bucket(a.release());
++constructed;
} else {
new (boost::addressof(*constructed)) bucket();
++constructed;
}
} }
BOOST_CATCH(...)
{
for (bucket_pointer p = new_buckets; p != constructed; ++p) {
boost::unordered::detail::func::destroy(boost::addressof(*p));
}
bucket_allocator_traits::deallocate(
bucket_alloc(), new_buckets, length);
BOOST_RETHROW;
}
BOOST_CATCH_END
// nothrow from here...
bucket_count_ = new_count; bucket_count_ = new_count;
buckets_ = new_buckets;
recalculate_max_load(); recalculate_max_load();
bucket_pointer end = buckets_ + static_cast<std::ptrdiff_t>(new_count);
for (bucket_pointer i = buckets_; i != end; ++i) {
new (boost::addressof(*i)) bucket();
}
new (boost::addressof(*end)) bucket(dummy_node);
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////