mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-29 19:07:15 +02:00
Unordered: Generic copy/move implementation.
[SVN r80379]
This commit is contained in:
@ -710,20 +710,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// copy_buckets_to
|
||||
//
|
||||
// Basic exception safety. If an exception is thrown this will
|
||||
// leave dst partially filled and the buckets unset.
|
||||
// fill_buckets
|
||||
|
||||
static void copy_buckets_to(buckets const& src, buckets& dst)
|
||||
template <class NodeCreator>
|
||||
static void fill_buckets(iterator n, buckets& dst,
|
||||
NodeCreator& creator)
|
||||
{
|
||||
BOOST_ASSERT(!dst.buckets_);
|
||||
|
||||
dst.create_buckets(dst.bucket_count_);
|
||||
|
||||
node_constructor a(dst.node_alloc());
|
||||
|
||||
iterator n = src.get_start();
|
||||
previous_pointer prev = dst.get_previous_start();
|
||||
|
||||
while (n.node_) {
|
||||
@ -733,10 +725,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
static_cast<node_pointer>(n.node_->group_prev_)->next_
|
||||
));
|
||||
|
||||
a.construct_node();
|
||||
a.construct_value2(*n);
|
||||
|
||||
node_pointer first_node = a.release();
|
||||
node_pointer first_node = creator.create(*n);
|
||||
node_pointer end = first_node;
|
||||
first_node->hash_ = key_hash;
|
||||
prev->next_ = static_cast<link_pointer>(first_node);
|
||||
@ -744,56 +733,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
for (++n; n != group_end; ++n)
|
||||
{
|
||||
a.construct_node();
|
||||
a.construct_value2(*n);
|
||||
end = a.release();
|
||||
end->hash_ = key_hash;
|
||||
add_after_node(end, first_node);
|
||||
++dst.size_;
|
||||
}
|
||||
|
||||
prev = place_in_bucket(dst, prev, end);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// move_buckets_to
|
||||
//
|
||||
// Basic exception safety. The source nodes are left in an unusable
|
||||
// state if an exception throws.
|
||||
|
||||
static void move_buckets_to(buckets& src, buckets& dst)
|
||||
{
|
||||
BOOST_ASSERT(!dst.buckets_);
|
||||
|
||||
dst.create_buckets(dst.bucket_count_);
|
||||
|
||||
node_constructor a(dst.node_alloc());
|
||||
|
||||
iterator n = src.get_start();
|
||||
previous_pointer prev = dst.get_previous_start();
|
||||
|
||||
while (n.node_) {
|
||||
std::size_t key_hash = n.node_->hash_;
|
||||
iterator group_end(
|
||||
static_cast<node_pointer>(
|
||||
static_cast<node_pointer>(n.node_->group_prev_)->next_
|
||||
));
|
||||
|
||||
a.construct_node();
|
||||
a.construct_value2(boost::move(*n));
|
||||
|
||||
node_pointer first_node = a.release();
|
||||
node_pointer end = first_node;
|
||||
first_node->hash_ = key_hash;
|
||||
prev->next_ = static_cast<link_pointer>(first_node);
|
||||
++dst.size_;
|
||||
|
||||
for(++n; n != group_end; ++n)
|
||||
{
|
||||
a.construct_node();
|
||||
a.construct_value2(boost::move(*n));
|
||||
end = a.release();
|
||||
end = creator.create(*n);
|
||||
end->hash_ = key_hash;
|
||||
add_after_node(end, first_node);
|
||||
++dst.size_;
|
||||
|
@ -54,6 +54,45 @@ namespace boost { namespace unordered { namespace detail {
|
||||
value_base& operator=(value_base const&);
|
||||
};
|
||||
|
||||
template <typename NodeAlloc>
|
||||
struct copy_nodes
|
||||
{
|
||||
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
|
||||
node_allocator_traits;
|
||||
|
||||
node_constructor<NodeAlloc> constructor;
|
||||
|
||||
explicit copy_nodes(NodeAlloc& a) : constructor(a) {}
|
||||
|
||||
typename node_allocator_traits::pointer create(
|
||||
typename node_allocator_traits::value_type::value_type const& v)
|
||||
{
|
||||
constructor.construct_node();
|
||||
constructor.construct_value2(v);
|
||||
return constructor.release();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename NodeAlloc>
|
||||
struct move_nodes
|
||||
{
|
||||
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
|
||||
node_allocator_traits;
|
||||
|
||||
node_constructor<NodeAlloc> constructor;
|
||||
|
||||
explicit move_nodes(NodeAlloc& a) : constructor(a) {}
|
||||
|
||||
typename node_allocator_traits::pointer create(
|
||||
typename node_allocator_traits::value_type::value_type& v)
|
||||
{
|
||||
constructor.construct_node();
|
||||
constructor.construct_value2(boost::move(v));
|
||||
return constructor.release();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Types>
|
||||
struct table :
|
||||
boost::unordered::detail::buckets<
|
||||
@ -173,7 +212,9 @@ namespace boost { namespace unordered { namespace detail {
|
||||
max_load_(0)
|
||||
{
|
||||
if(x.size_) {
|
||||
table_impl::copy_buckets_to(x, *this);
|
||||
this->create_buckets(this->bucket_count_);
|
||||
copy_nodes<node_allocator> copy(this->node_alloc());
|
||||
table_impl::fill_buckets(x.get_start(), *this, copy);
|
||||
this->max_load_ = calculate_max_load();
|
||||
}
|
||||
}
|
||||
@ -199,11 +240,15 @@ namespace boost { namespace unordered { namespace detail {
|
||||
this->move_buckets_from(x);
|
||||
}
|
||||
else if(x.size_) {
|
||||
// Use a temporary table because move_buckets_to leaves the
|
||||
// Use a temporary table because moving the nodes leaves the
|
||||
// source container in a complete mess.
|
||||
|
||||
buckets tmp(x, m);
|
||||
table_impl::move_buckets_to(tmp, *this);
|
||||
|
||||
this->create_buckets(this->bucket_count_);
|
||||
move_nodes<node_allocator> move(this->node_alloc());
|
||||
table_impl::fill_buckets(tmp.get_start(), *this, move);
|
||||
|
||||
this->max_load_ = calculate_max_load();
|
||||
}
|
||||
}
|
||||
@ -271,7 +316,11 @@ namespace boost { namespace unordered { namespace detail {
|
||||
buckets b(this->node_alloc(),
|
||||
x.min_buckets_for_size(x.size_));
|
||||
buckets tmp(x, move_tag());
|
||||
table_impl::move_buckets_to(tmp, b);
|
||||
|
||||
b.create_buckets(b.bucket_count_);
|
||||
move_nodes<node_allocator> move(b.node_alloc());
|
||||
table_impl::fill_buckets(tmp.get_start(), b, move);
|
||||
|
||||
b.swap(*this);
|
||||
}
|
||||
else {
|
||||
|
@ -617,58 +617,16 @@ namespace boost { namespace unordered { namespace detail {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// copy_buckets_to
|
||||
//
|
||||
// Basic exception safety. If an exception is thrown this will
|
||||
// leave dst partially filled and the buckets unset.
|
||||
// fill_buckets
|
||||
|
||||
static void copy_buckets_to(buckets const& src, buckets& dst)
|
||||
template <class NodeCreator>
|
||||
static void fill_buckets(iterator n, buckets& dst,
|
||||
NodeCreator& creator)
|
||||
{
|
||||
BOOST_ASSERT(!dst.buckets_);
|
||||
|
||||
dst.create_buckets(dst.bucket_count_);
|
||||
|
||||
node_constructor a(dst.node_alloc());
|
||||
|
||||
iterator n = src.get_start();
|
||||
previous_pointer prev = dst.get_previous_start();
|
||||
|
||||
while(n.node_) {
|
||||
a.construct_node();
|
||||
a.construct_value2(*n);
|
||||
|
||||
node_pointer node = a.release();
|
||||
node->hash_ = n.node_->hash_;
|
||||
prev->next_ = static_cast<link_pointer>(node);
|
||||
++dst.size_;
|
||||
++n;
|
||||
|
||||
prev = place_in_bucket(dst, prev);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// move_buckets_to
|
||||
//
|
||||
// Basic exception safety. The source nodes are left in an unusable
|
||||
// state if an exception throws.
|
||||
|
||||
static void move_buckets_to(buckets& src, buckets& dst)
|
||||
{
|
||||
BOOST_ASSERT(!dst.buckets_);
|
||||
|
||||
dst.create_buckets(dst.bucket_count_);
|
||||
|
||||
node_constructor a(dst.node_alloc());
|
||||
|
||||
iterator n = src.get_start();
|
||||
previous_pointer prev = dst.get_previous_start();
|
||||
|
||||
while (n.node_) {
|
||||
a.construct_node();
|
||||
a.construct_value2(boost::move(*n));
|
||||
|
||||
node_pointer node = a.release();
|
||||
node_pointer node = creator.create(*n);
|
||||
node->hash_ = n.node_->hash_;
|
||||
prev->next_ = static_cast<link_pointer>(node);
|
||||
++dst.size_;
|
||||
|
Reference in New Issue
Block a user