diff --git a/include/boost/unordered/detail/buckets.hpp b/include/boost/unordered/detail/buckets.hpp index 4dfe0445..ec79913a 100644 --- a/include/boost/unordered/detail/buckets.hpp +++ b/include/boost/unordered/detail/buckets.hpp @@ -684,38 +684,59 @@ namespace boost { namespace unordered { namespace detail { } buckets(buckets& b, boost::unordered::detail::move_tag m) : - buckets_(), + buckets_(b.buckets_), bucket_count_(b.bucket_count_), - size_(), + size_(b.size_), allocators_(b.allocators_, m) { - swap(b); + b.buckets_ = bucket_pointer(); + b.size_ = 0; } template buckets(boost::unordered::detail::table& x, boost::unordered::detail::move_tag m) : - buckets_(), + buckets_(x.buckets_), bucket_count_(x.bucket_count_), - size_(), + size_(x.size_), allocators_(x.allocators_, m) { - swap(x); + x.buckets_ = bucket_pointer(); + x.size_ = 0; } //////////////////////////////////////////////////////////////////////// // Create buckets // (never called in constructor to avoid exception issues) - void create_buckets() + void create_buckets(std::size_t new_count) { boost::unordered::detail::array_constructor constructor(bucket_alloc()); // Creates an extra bucket to act as the start node. - constructor.construct(bucket(), this->bucket_count_ + 1); + constructor.construct(bucket(), new_count + 1); - if (bucket::extra_node) + if (buckets_) + { + // Copy the nodes to the new buckets, including the dummy + // node if there is one. + (constructor.get() + + static_cast(new_count))->next_ = + (buckets_ + static_cast( + bucket_count_))->next_; + + bucket_pointer end = this->get_bucket(this->bucket_count_ + 1); + for(bucket_pointer it = this->buckets_; it != end; ++it) + { + bucket_allocator_traits::destroy(bucket_alloc(), + boost::addressof(*it)); + } + + bucket_allocator_traits::deallocate(bucket_alloc(), + this->buckets_, this->bucket_count_ + 1); + } + else if (bucket::extra_node) { node_constructor a(this->node_alloc()); a.construct_node(); @@ -725,6 +746,7 @@ namespace boost { namespace unordered { namespace detail { a.release(); } + this->bucket_count_ = new_count; this->buckets_ = constructor.release(); } @@ -755,7 +777,6 @@ namespace boost { namespace unordered { namespace detail { this->bucket_count_ = other.bucket_count_; this->size_ = other.size_; other.buckets_ = bucket_pointer(); - other.bucket_count_ = 0; other.size_ = 0; } diff --git a/include/boost/unordered/detail/equivalent.hpp b/include/boost/unordered/detail/equivalent.hpp index 54ace45f..8e3252a3 100644 --- a/include/boost/unordered/detail/equivalent.hpp +++ b/include/boost/unordered/detail/equivalent.hpp @@ -719,7 +719,7 @@ namespace boost { namespace unordered { namespace detail { { BOOST_ASSERT(!dst.buckets_); - dst.create_buckets(); + dst.create_buckets(dst.bucket_count_); node_constructor a(dst.node_alloc()); @@ -766,7 +766,7 @@ namespace boost { namespace unordered { namespace detail { { BOOST_ASSERT(!dst.buckets_); - dst.create_buckets(); + dst.create_buckets(dst.bucket_count_); node_constructor a(dst.node_alloc()); @@ -808,26 +808,12 @@ namespace boost { namespace unordered { namespace detail { { BOOST_ASSERT(this->size_); - buckets dst(this->node_alloc(), num_buckets); - dst.create_buckets(); - - previous_pointer src_start = this->get_previous_start(); - previous_pointer dst_start = dst.get_previous_start(); - - dst_start->next_ = src_start->next_; - src_start->next_ = link_pointer(); - dst.size_ = this->size_; - this->size_ = 0; - - previous_pointer prev = dst_start; + this->create_buckets(num_buckets); + previous_pointer prev = this->get_previous_start(); while (prev->next_) - prev = place_in_bucket(dst, prev, + prev = place_in_bucket(*this, prev, static_cast( static_cast(prev->next_)->group_prev_)); - - // Swap the new nodes back into the container and setup the - // variables. - dst.swap(*this); // no throw } // Iterate through the nodes placing them in the correct buckets. diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index 116c4e9c..5951e729 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -196,7 +196,7 @@ namespace boost { namespace unordered { namespace detail { max_load_(x.max_load_) { if(a == x.node_alloc()) { - this->buckets::swap(x, false_type()); + this->move_buckets_from(x); } else if(x.size_) { // Use a temporary table because move_buckets_to leaves the @@ -403,9 +403,8 @@ namespace boost { namespace unordered { namespace detail { inline void table::reserve_for_insert(std::size_t size) { if (!this->buckets_) { - this->bucket_count_ = (std::max)(this->bucket_count_, - this->min_buckets_for_size(size)); - this->create_buckets(); + this->create_buckets((std::max)(this->bucket_count_, + this->min_buckets_for_size(size))); this->max_load_ = this->calculate_max_load(); } // According to the standard this should be 'size >= max_load_', diff --git a/include/boost/unordered/detail/unique.hpp b/include/boost/unordered/detail/unique.hpp index 34cfea25..0e5c20b2 100644 --- a/include/boost/unordered/detail/unique.hpp +++ b/include/boost/unordered/detail/unique.hpp @@ -626,7 +626,7 @@ namespace boost { namespace unordered { namespace detail { { BOOST_ASSERT(!dst.buckets_); - dst.create_buckets(); + dst.create_buckets(dst.bucket_count_); node_constructor a(dst.node_alloc()); @@ -657,7 +657,7 @@ namespace boost { namespace unordered { namespace detail { { BOOST_ASSERT(!dst.buckets_); - dst.create_buckets(); + dst.create_buckets(dst.bucket_count_); node_constructor a(dst.node_alloc()); @@ -683,24 +683,10 @@ namespace boost { namespace unordered { namespace detail { { BOOST_ASSERT(this->size_); - buckets dst(this->node_alloc(), num_buckets); - dst.create_buckets(); - - previous_pointer src_start = this->get_previous_start(); - previous_pointer dst_start = dst.get_previous_start(); - - dst_start->next_ = src_start->next_; - src_start->next_ = link_pointer(); - dst.size_ = this->size_; - this->size_ = 0; - - previous_pointer prev = dst.get_previous_start(); + this->create_buckets(num_buckets); + previous_pointer prev = this->get_previous_start(); while (prev->next_) - prev = place_in_bucket(dst, prev); - - // Swap the new nodes back into the container and setup the - // variables. - dst.swap(*this); // no throw + prev = place_in_bucket(*this, prev); } // Iterate through the nodes placing them in the correct buckets.