mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-30 03:17: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
|
// fill_buckets
|
||||||
//
|
|
||||||
// Basic exception safety. If an exception is thrown this will
|
|
||||||
// leave dst partially filled and the buckets unset.
|
|
||||||
|
|
||||||
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();
|
previous_pointer prev = dst.get_previous_start();
|
||||||
|
|
||||||
while (n.node_) {
|
while (n.node_) {
|
||||||
@ -733,10 +725,7 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
static_cast<node_pointer>(n.node_->group_prev_)->next_
|
static_cast<node_pointer>(n.node_->group_prev_)->next_
|
||||||
));
|
));
|
||||||
|
|
||||||
a.construct_node();
|
node_pointer first_node = creator.create(*n);
|
||||||
a.construct_value2(*n);
|
|
||||||
|
|
||||||
node_pointer first_node = a.release();
|
|
||||||
node_pointer end = first_node;
|
node_pointer end = first_node;
|
||||||
first_node->hash_ = key_hash;
|
first_node->hash_ = key_hash;
|
||||||
prev->next_ = static_cast<link_pointer>(first_node);
|
prev->next_ = static_cast<link_pointer>(first_node);
|
||||||
@ -744,56 +733,7 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
|
|
||||||
for (++n; n != group_end; ++n)
|
for (++n; n != group_end; ++n)
|
||||||
{
|
{
|
||||||
a.construct_node();
|
end = creator.create(*n);
|
||||||
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->hash_ = key_hash;
|
end->hash_ = key_hash;
|
||||||
add_after_node(end, first_node);
|
add_after_node(end, first_node);
|
||||||
++dst.size_;
|
++dst.size_;
|
||||||
|
@ -54,6 +54,45 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
value_base& operator=(value_base const&);
|
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>
|
template <typename Types>
|
||||||
struct table :
|
struct table :
|
||||||
boost::unordered::detail::buckets<
|
boost::unordered::detail::buckets<
|
||||||
@ -173,7 +212,9 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
max_load_(0)
|
max_load_(0)
|
||||||
{
|
{
|
||||||
if(x.size_) {
|
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();
|
this->max_load_ = calculate_max_load();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,11 +240,15 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
this->move_buckets_from(x);
|
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 moving the nodes leaves the
|
||||||
// source container in a complete mess.
|
// source container in a complete mess.
|
||||||
|
|
||||||
buckets tmp(x, m);
|
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();
|
this->max_load_ = calculate_max_load();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,7 +316,11 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
buckets b(this->node_alloc(),
|
buckets b(this->node_alloc(),
|
||||||
x.min_buckets_for_size(x.size_));
|
x.min_buckets_for_size(x.size_));
|
||||||
buckets tmp(x, move_tag());
|
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);
|
b.swap(*this);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -617,58 +617,16 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// copy_buckets_to
|
// fill_buckets
|
||||||
//
|
|
||||||
// Basic exception safety. If an exception is thrown this will
|
|
||||||
// leave dst partially filled and the buckets unset.
|
|
||||||
|
|
||||||
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();
|
previous_pointer prev = dst.get_previous_start();
|
||||||
|
|
||||||
while (n.node_) {
|
while (n.node_) {
|
||||||
a.construct_node();
|
node_pointer node = creator.create(*n);
|
||||||
a.construct_value2(boost::move(*n));
|
|
||||||
|
|
||||||
node_pointer node = a.release();
|
|
||||||
node->hash_ = n.node_->hash_;
|
node->hash_ = n.node_->hash_;
|
||||||
prev->next_ = static_cast<link_pointer>(node);
|
prev->next_ = static_cast<link_pointer>(node);
|
||||||
++dst.size_;
|
++dst.size_;
|
||||||
|
Reference in New Issue
Block a user