forked from boostorg/unordered
Unordered: Avoid unnecessary swapping in rehash and move.
[SVN r80378]
This commit is contained in:
@ -684,38 +684,59 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buckets(buckets& b, boost::unordered::detail::move_tag m) :
|
buckets(buckets& b, boost::unordered::detail::move_tag m) :
|
||||||
buckets_(),
|
buckets_(b.buckets_),
|
||||||
bucket_count_(b.bucket_count_),
|
bucket_count_(b.bucket_count_),
|
||||||
size_(),
|
size_(b.size_),
|
||||||
allocators_(b.allocators_, m)
|
allocators_(b.allocators_, m)
|
||||||
{
|
{
|
||||||
swap(b);
|
b.buckets_ = bucket_pointer();
|
||||||
|
b.size_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Types>
|
template <typename Types>
|
||||||
buckets(boost::unordered::detail::table<Types>& x,
|
buckets(boost::unordered::detail::table<Types>& x,
|
||||||
boost::unordered::detail::move_tag m) :
|
boost::unordered::detail::move_tag m) :
|
||||||
buckets_(),
|
buckets_(x.buckets_),
|
||||||
bucket_count_(x.bucket_count_),
|
bucket_count_(x.bucket_count_),
|
||||||
size_(),
|
size_(x.size_),
|
||||||
allocators_(x.allocators_, m)
|
allocators_(x.allocators_, m)
|
||||||
{
|
{
|
||||||
swap(x);
|
x.buckets_ = bucket_pointer();
|
||||||
|
x.size_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Create buckets
|
// Create buckets
|
||||||
// (never called in constructor to avoid exception issues)
|
// (never called in constructor to avoid exception issues)
|
||||||
|
|
||||||
void create_buckets()
|
void create_buckets(std::size_t new_count)
|
||||||
{
|
{
|
||||||
boost::unordered::detail::array_constructor<bucket_allocator>
|
boost::unordered::detail::array_constructor<bucket_allocator>
|
||||||
constructor(bucket_alloc());
|
constructor(bucket_alloc());
|
||||||
|
|
||||||
// Creates an extra bucket to act as the start node.
|
// 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<std::ptrdiff_t>(new_count))->next_ =
|
||||||
|
(buckets_ + static_cast<std::ptrdiff_t>(
|
||||||
|
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());
|
node_constructor a(this->node_alloc());
|
||||||
a.construct_node();
|
a.construct_node();
|
||||||
@ -725,6 +746,7 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
a.release();
|
a.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->bucket_count_ = new_count;
|
||||||
this->buckets_ = constructor.release();
|
this->buckets_ = constructor.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -755,7 +777,6 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
this->bucket_count_ = other.bucket_count_;
|
this->bucket_count_ = other.bucket_count_;
|
||||||
this->size_ = other.size_;
|
this->size_ = other.size_;
|
||||||
other.buckets_ = bucket_pointer();
|
other.buckets_ = bucket_pointer();
|
||||||
other.bucket_count_ = 0;
|
|
||||||
other.size_ = 0;
|
other.size_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -719,7 +719,7 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
{
|
{
|
||||||
BOOST_ASSERT(!dst.buckets_);
|
BOOST_ASSERT(!dst.buckets_);
|
||||||
|
|
||||||
dst.create_buckets();
|
dst.create_buckets(dst.bucket_count_);
|
||||||
|
|
||||||
node_constructor a(dst.node_alloc());
|
node_constructor a(dst.node_alloc());
|
||||||
|
|
||||||
@ -766,7 +766,7 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
{
|
{
|
||||||
BOOST_ASSERT(!dst.buckets_);
|
BOOST_ASSERT(!dst.buckets_);
|
||||||
|
|
||||||
dst.create_buckets();
|
dst.create_buckets(dst.bucket_count_);
|
||||||
|
|
||||||
node_constructor a(dst.node_alloc());
|
node_constructor a(dst.node_alloc());
|
||||||
|
|
||||||
@ -808,26 +808,12 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
{
|
{
|
||||||
BOOST_ASSERT(this->size_);
|
BOOST_ASSERT(this->size_);
|
||||||
|
|
||||||
buckets dst(this->node_alloc(), num_buckets);
|
this->create_buckets(num_buckets);
|
||||||
dst.create_buckets();
|
previous_pointer prev = this->get_previous_start();
|
||||||
|
|
||||||
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;
|
|
||||||
while (prev->next_)
|
while (prev->next_)
|
||||||
prev = place_in_bucket(dst, prev,
|
prev = place_in_bucket(*this, prev,
|
||||||
static_cast<node_pointer>(
|
static_cast<node_pointer>(
|
||||||
static_cast<node_pointer>(prev->next_)->group_prev_));
|
static_cast<node_pointer>(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.
|
// Iterate through the nodes placing them in the correct buckets.
|
||||||
|
@ -196,7 +196,7 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
max_load_(x.max_load_)
|
max_load_(x.max_load_)
|
||||||
{
|
{
|
||||||
if(a == x.node_alloc()) {
|
if(a == x.node_alloc()) {
|
||||||
this->buckets::swap(x, false_type());
|
this->move_buckets_from(x);
|
||||||
}
|
}
|
||||||
else if(x.size_) {
|
else if(x.size_) {
|
||||||
// Use a temporary table because move_buckets_to leaves the
|
// Use a temporary table because move_buckets_to leaves the
|
||||||
@ -403,9 +403,8 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
inline void table<Types>::reserve_for_insert(std::size_t size)
|
inline void table<Types>::reserve_for_insert(std::size_t size)
|
||||||
{
|
{
|
||||||
if (!this->buckets_) {
|
if (!this->buckets_) {
|
||||||
this->bucket_count_ = (std::max)(this->bucket_count_,
|
this->create_buckets((std::max)(this->bucket_count_,
|
||||||
this->min_buckets_for_size(size));
|
this->min_buckets_for_size(size)));
|
||||||
this->create_buckets();
|
|
||||||
this->max_load_ = this->calculate_max_load();
|
this->max_load_ = this->calculate_max_load();
|
||||||
}
|
}
|
||||||
// According to the standard this should be 'size >= max_load_',
|
// According to the standard this should be 'size >= max_load_',
|
||||||
|
@ -626,7 +626,7 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
{
|
{
|
||||||
BOOST_ASSERT(!dst.buckets_);
|
BOOST_ASSERT(!dst.buckets_);
|
||||||
|
|
||||||
dst.create_buckets();
|
dst.create_buckets(dst.bucket_count_);
|
||||||
|
|
||||||
node_constructor a(dst.node_alloc());
|
node_constructor a(dst.node_alloc());
|
||||||
|
|
||||||
@ -657,7 +657,7 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
{
|
{
|
||||||
BOOST_ASSERT(!dst.buckets_);
|
BOOST_ASSERT(!dst.buckets_);
|
||||||
|
|
||||||
dst.create_buckets();
|
dst.create_buckets(dst.bucket_count_);
|
||||||
|
|
||||||
node_constructor a(dst.node_alloc());
|
node_constructor a(dst.node_alloc());
|
||||||
|
|
||||||
@ -683,24 +683,10 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
{
|
{
|
||||||
BOOST_ASSERT(this->size_);
|
BOOST_ASSERT(this->size_);
|
||||||
|
|
||||||
buckets dst(this->node_alloc(), num_buckets);
|
this->create_buckets(num_buckets);
|
||||||
dst.create_buckets();
|
previous_pointer prev = this->get_previous_start();
|
||||||
|
|
||||||
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();
|
|
||||||
while (prev->next_)
|
while (prev->next_)
|
||||||
prev = place_in_bucket(dst, prev);
|
prev = place_in_bucket(*this, 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.
|
// Iterate through the nodes placing them in the correct buckets.
|
||||||
|
Reference in New Issue
Block a user