mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-29 19:07:15 +02:00
Change how node construction works.
Split node_constructor into two classes, one for constructing a node without a value, and then another for holding it once the value is constructed. Do the work of constructing values in convenience functions in allocate.hpp (construct_value_generic, construct_value, construct_pair).
This commit is contained in:
@ -808,6 +808,18 @@ namespace boost { namespace unordered { namespace detail { namespace func {
|
||||
# endif
|
||||
|
||||
#else
|
||||
template <typename Alloc, typename T>
|
||||
inline void call_construct(Alloc&, T* address)
|
||||
{
|
||||
new ((void*) address) T();
|
||||
}
|
||||
|
||||
template <typename Alloc, typename T, typename A0>
|
||||
inline void call_construct(Alloc&, T* address,
|
||||
BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
new ((void*) address) T(boost::forward<A0>(a0));
|
||||
}
|
||||
|
||||
template <typename Alloc, typename T>
|
||||
inline void destroy_value_impl(Alloc&, T* x) {
|
||||
@ -1049,6 +1061,46 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
|
||||
|
||||
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
|
||||
// Some nicer construct_value functions, might try to
|
||||
// improve implementation later.
|
||||
|
||||
template <typename AllocAndPointer, BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
inline typename AllocAndPointer::node_pointer construct_value_generic(AllocAndPointer& a, BOOST_UNORDERED_EMPLACE_ARGS) {
|
||||
construct_value_impl(a.alloc_, a.node_->value_ptr(),
|
||||
BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
return a.release();
|
||||
}
|
||||
|
||||
template <typename AllocAndPointer, typename U>
|
||||
inline typename AllocAndPointer::node_pointer construct_value(AllocAndPointer& a, BOOST_FWD_REF(U) x) {
|
||||
boost::unordered::detail::func::call_construct(
|
||||
a.alloc_, a.node_->value_ptr(), boost::forward<U>(x));
|
||||
return a.release();
|
||||
}
|
||||
|
||||
// TODO: When possible, it might be better to use std::pair's
|
||||
// constructor for std::piece_construct with std::tuple.
|
||||
template <typename AllocAndPointer, typename Key>
|
||||
inline typename AllocAndPointer::node_pointer construct_pair(AllocAndPointer& a, BOOST_FWD_REF(Key) k) {
|
||||
boost::unordered::detail::func::call_construct(
|
||||
a.alloc_, boost::addressof(a.node_->value_ptr()->first),
|
||||
boost::forward<Key>(k));
|
||||
boost::unordered::detail::func::call_construct(
|
||||
a.alloc_, boost::addressof(a.node_->value_ptr()->second));
|
||||
return a.release();
|
||||
}
|
||||
|
||||
template <typename AllocAndPointer, typename Key, typename Mapped>
|
||||
inline typename AllocAndPointer::node_pointer construct_pair(AllocAndPointer& a,
|
||||
BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m) {
|
||||
boost::unordered::detail::func::call_construct(
|
||||
a.alloc_, boost::addressof(a.node_->value_ptr()->first),
|
||||
boost::forward<Key>(k));
|
||||
boost::unordered::detail::func::call_construct(
|
||||
a.alloc_, boost::addressof(a.node_->value_ptr()->second),
|
||||
boost::forward<Mapped>(m));
|
||||
return a.release();
|
||||
}
|
||||
}}}}
|
||||
|
||||
namespace boost { namespace unordered { namespace detail {
|
||||
|
@ -324,8 +324,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
template <typename NodeAlloc>
|
||||
struct node_constructor
|
||||
{
|
||||
private:
|
||||
|
||||
typedef NodeAlloc node_allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
|
||||
node_allocator_traits;
|
||||
@ -333,50 +331,20 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename node_allocator_traits::pointer node_pointer;
|
||||
typedef typename node::value_type value_type;
|
||||
|
||||
protected:
|
||||
|
||||
node_allocator& alloc_;
|
||||
node_pointer node_;
|
||||
bool node_constructed_;
|
||||
bool value_constructed_;
|
||||
|
||||
public:
|
||||
|
||||
node_constructor(node_allocator& n) :
|
||||
alloc_(n),
|
||||
node_(),
|
||||
node_constructed_(false),
|
||||
value_constructed_(false)
|
||||
node_constructed_(false)
|
||||
{
|
||||
}
|
||||
|
||||
~node_constructor();
|
||||
|
||||
void construct();
|
||||
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
void construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
construct();
|
||||
boost::unordered::detail::func::construct_value_impl(
|
||||
alloc_, node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
value_constructed_ = true;
|
||||
}
|
||||
|
||||
template <typename A0>
|
||||
void construct_with_value2(BOOST_FWD_REF(A0) a0)
|
||||
{
|
||||
construct();
|
||||
boost::unordered::detail::func::construct_value_impl(
|
||||
alloc_, node_->value_ptr(),
|
||||
BOOST_UNORDERED_EMPLACE_ARGS1(boost::forward<A0>(a0)));
|
||||
value_constructed_ = true;
|
||||
}
|
||||
|
||||
value_type const& value() const {
|
||||
BOOST_ASSERT(node_ && node_constructed_ && value_constructed_);
|
||||
return node_->value();
|
||||
}
|
||||
void create_node();
|
||||
|
||||
// no throw
|
||||
node_pointer release()
|
||||
@ -387,6 +355,14 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return p;
|
||||
}
|
||||
|
||||
void reclaim(node_pointer p) {
|
||||
BOOST_ASSERT(!node_);
|
||||
node_ = p;
|
||||
node_constructed_ = true;
|
||||
boost::unordered::detail::func::destroy_value_impl(alloc_,
|
||||
node_->value_ptr());
|
||||
}
|
||||
|
||||
private:
|
||||
node_constructor(node_constructor const&);
|
||||
node_constructor& operator=(node_constructor const&);
|
||||
@ -396,11 +372,6 @@ namespace boost { namespace unordered { namespace detail {
|
||||
node_constructor<Alloc>::~node_constructor()
|
||||
{
|
||||
if (node_) {
|
||||
if (value_constructed_) {
|
||||
boost::unordered::detail::func::destroy_value_impl(alloc_,
|
||||
node_->value_ptr());
|
||||
}
|
||||
|
||||
if (node_constructed_) {
|
||||
boost::unordered::detail::func::destroy(
|
||||
boost::addressof(*node_));
|
||||
@ -411,27 +382,66 @@ namespace boost { namespace unordered { namespace detail {
|
||||
}
|
||||
|
||||
template <typename Alloc>
|
||||
void node_constructor<Alloc>::construct()
|
||||
void node_constructor<Alloc>::create_node()
|
||||
{
|
||||
if(!node_) {
|
||||
node_constructed_ = false;
|
||||
value_constructed_ = false;
|
||||
BOOST_ASSERT(!node_);
|
||||
node_constructed_ = false;
|
||||
|
||||
node_ = node_allocator_traits::allocate(alloc_, 1);
|
||||
node_ = node_allocator_traits::allocate(alloc_, 1);
|
||||
|
||||
new ((void*) boost::addressof(*node_)) node();
|
||||
node_->init(node_);
|
||||
node_constructed_ = true;
|
||||
new ((void*) boost::addressof(*node_)) node();
|
||||
node_->init(node_);
|
||||
node_constructed_ = true;
|
||||
}
|
||||
|
||||
template <typename NodeAlloc>
|
||||
struct node_tmp
|
||||
{
|
||||
private:
|
||||
|
||||
typedef NodeAlloc node_allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
|
||||
node_allocator_traits;
|
||||
typedef typename node_allocator_traits::value_type node;
|
||||
typedef typename node_allocator_traits::pointer node_pointer;
|
||||
typedef typename node::value_type value_type;
|
||||
|
||||
public:
|
||||
|
||||
node_allocator& alloc_;
|
||||
node_pointer node_;
|
||||
|
||||
explicit node_tmp(node_pointer n, node_allocator& a):
|
||||
alloc_(a),
|
||||
node_(n)
|
||||
{
|
||||
}
|
||||
else {
|
||||
BOOST_ASSERT(node_constructed_);
|
||||
|
||||
if (value_constructed_)
|
||||
{
|
||||
boost::unordered::detail::func::destroy_value_impl(alloc_,
|
||||
node_->value_ptr());
|
||||
value_constructed_ = false;
|
||||
}
|
||||
~node_tmp();
|
||||
|
||||
value_type const& value() const {
|
||||
BOOST_ASSERT(node_ );
|
||||
return node_->value();
|
||||
}
|
||||
|
||||
// no throw
|
||||
node_pointer release()
|
||||
{
|
||||
node_pointer p = node_;
|
||||
node_ = node_pointer();
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Alloc>
|
||||
node_tmp<Alloc>::~node_tmp()
|
||||
{
|
||||
if (node_) {
|
||||
boost::unordered::detail::func::destroy_value_impl(alloc_,
|
||||
node_->value_ptr());
|
||||
boost::unordered::detail::func::destroy(
|
||||
boost::addressof(*node_));
|
||||
node_allocator_traits::deallocate(alloc_, node_, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -442,11 +452,9 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// Temporary store for nodes. Deletes any that aren't used.
|
||||
|
||||
template <typename NodeAlloc>
|
||||
struct node_holder : private node_constructor<NodeAlloc>
|
||||
struct node_holder
|
||||
{
|
||||
private:
|
||||
typedef node_constructor<NodeAlloc> base;
|
||||
|
||||
typedef NodeAlloc node_allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
|
||||
node_allocator_traits;
|
||||
@ -456,13 +464,14 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename node::link_pointer link_pointer;
|
||||
typedef boost::unordered::iterator_detail::iterator<node> iterator;
|
||||
|
||||
node_constructor<NodeAlloc> constructor_;
|
||||
node_pointer nodes_;
|
||||
|
||||
public:
|
||||
|
||||
template <typename Table>
|
||||
explicit node_holder(Table& b) :
|
||||
base(b.node_alloc()),
|
||||
constructor_(b.node_alloc()),
|
||||
nodes_()
|
||||
{
|
||||
if (b.size_) {
|
||||
@ -475,61 +484,63 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
~node_holder();
|
||||
|
||||
void node_for_assignment()
|
||||
node_pointer pop_node()
|
||||
{
|
||||
if (!this->node_ && nodes_) {
|
||||
this->node_ = nodes_;
|
||||
nodes_ = static_cast<node_pointer>(nodes_->next_);
|
||||
this->node_->init(this->node_);
|
||||
this->node_->next_ = link_pointer();
|
||||
|
||||
this->node_constructed_ = true;
|
||||
this->value_constructed_ = true;
|
||||
}
|
||||
node_pointer n = nodes_;
|
||||
nodes_ = static_cast<node_pointer>(nodes_->next_);
|
||||
n->init(n);
|
||||
n->next_ = link_pointer();
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void assign_impl(T const& v) {
|
||||
if (this->node_ && this->value_constructed_) {
|
||||
this->node_->value() = v;
|
||||
inline node_pointer copy_of(T const& v) {
|
||||
if (nodes_) {
|
||||
node_tmp<NodeAlloc> a(pop_node(), constructor_.alloc_);
|
||||
a.node_->value() = v;
|
||||
return a.release();
|
||||
}
|
||||
else {
|
||||
this->construct_with_value2(v);
|
||||
constructor_.create_node();
|
||||
return boost::unordered::detail::func::construct_value(constructor_, v);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline void assign_impl(std::pair<T1 const, T2> const& v) {
|
||||
this->construct_with_value2(v);
|
||||
inline node_pointer copy_of(std::pair<T1 const, T2> const& v) {
|
||||
if (nodes_) {
|
||||
constructor_.reclaim(pop_node());
|
||||
}
|
||||
else {
|
||||
constructor_.create_node();
|
||||
}
|
||||
return boost::unordered::detail::func::construct_value(constructor_, v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void move_assign_impl(T& v) {
|
||||
if (this->node_ && this->value_constructed_) {
|
||||
this->node_->value() = boost::move(v);
|
||||
inline node_pointer move_copy_of(T& v) {
|
||||
if (nodes_) {
|
||||
node_tmp<NodeAlloc> a(pop_node(), constructor_.alloc_);
|
||||
a.node_->value() = boost::move(v);
|
||||
return a.release();
|
||||
}
|
||||
else {
|
||||
this->construct_with_value2(boost::move(v));
|
||||
constructor_.create_node();
|
||||
return boost::unordered::detail::func::construct_value(
|
||||
constructor_, boost::move(v));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline void move_assign_impl(std::pair<T1 const, T2>& v) {
|
||||
this->construct_with_value2(boost::move(v));
|
||||
}
|
||||
|
||||
node_pointer copy_of(value_type const& v)
|
||||
{
|
||||
node_for_assignment();
|
||||
assign_impl(v);
|
||||
return base::release();
|
||||
}
|
||||
|
||||
node_pointer move_copy_of(value_type& v)
|
||||
{
|
||||
node_for_assignment();
|
||||
move_assign_impl(v);
|
||||
return base::release();
|
||||
inline node_pointer move_copy_of(std::pair<T1 const, T2>& v) {
|
||||
if (nodes_) {
|
||||
constructor_.reclaim(pop_node());
|
||||
}
|
||||
else {
|
||||
constructor_.create_node();
|
||||
}
|
||||
return boost::unordered::detail::func::construct_value(
|
||||
constructor_, boost::move(v));
|
||||
}
|
||||
|
||||
iterator begin() const
|
||||
@ -545,10 +556,10 @@ namespace boost { namespace unordered { namespace detail {
|
||||
node_pointer p = nodes_;
|
||||
nodes_ = static_cast<node_pointer>(p->next_);
|
||||
|
||||
boost::unordered::detail::func::destroy_value_impl(this->alloc_,
|
||||
boost::unordered::detail::func::destroy_value_impl(constructor_.alloc_,
|
||||
p->value_ptr());
|
||||
boost::unordered::detail::func::destroy(boost::addressof(*p));
|
||||
node_allocator_traits::deallocate(this->alloc_, p, 1);
|
||||
node_allocator_traits::deallocate(constructor_.alloc_, p, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,6 +195,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename table::key_equal key_equal;
|
||||
typedef typename table::key_type key_type;
|
||||
typedef typename table::node_constructor node_constructor;
|
||||
typedef typename table::node_tmp node_tmp;
|
||||
typedef typename table::extractor extractor;
|
||||
typedef typename table::iterator iterator;
|
||||
typedef typename table::c_iterator c_iterator;
|
||||
@ -381,7 +382,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
}
|
||||
|
||||
inline iterator add_node(
|
||||
node_constructor& a,
|
||||
node_tmp& a,
|
||||
std::size_t key_hash,
|
||||
iterator pos)
|
||||
{
|
||||
@ -432,7 +433,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return iterator(n);
|
||||
}
|
||||
|
||||
iterator emplace_impl(node_constructor& a)
|
||||
iterator emplace_impl(node_tmp& a)
|
||||
{
|
||||
key_type const& k = this->get_key(a.value());
|
||||
std::size_t key_hash = this->hash(k);
|
||||
@ -444,7 +445,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
return this->add_node(a, key_hash, position);
|
||||
}
|
||||
|
||||
void emplace_impl_no_rehash(node_constructor& a)
|
||||
void emplace_impl_no_rehash(node_tmp& a)
|
||||
{
|
||||
key_type const& k = this->get_key(a.value());
|
||||
std::size_t key_hash = this->hash(k);
|
||||
@ -473,9 +474,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
|
||||
{
|
||||
node_constructor a(this->node_alloc());
|
||||
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
a.create_node();
|
||||
node_tmp b(
|
||||
boost::unordered::detail::func::construct_value_generic(a, BOOST_UNORDERED_EMPLACE_FORWARD),
|
||||
a.alloc_);
|
||||
|
||||
return iterator(emplace_impl(a));
|
||||
return iterator(emplace_impl(b));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@ -492,8 +496,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
std::size_t distance = std::distance(i, j);
|
||||
if(distance == 1) {
|
||||
node_constructor a(this->node_alloc());
|
||||
a.construct_with_value2(*i);
|
||||
emplace_impl(a);
|
||||
a.create_node();
|
||||
node_tmp b(
|
||||
boost::unordered::detail::func::construct_value(a, *i),
|
||||
a.alloc_);
|
||||
|
||||
emplace_impl(b);
|
||||
}
|
||||
else {
|
||||
// Only require basic exception safety here
|
||||
@ -501,8 +509,11 @@ namespace boost { namespace unordered { namespace detail {
|
||||
|
||||
node_constructor a(this->node_alloc());
|
||||
for (; i != j; ++i) {
|
||||
a.construct_with_value2(*i);
|
||||
emplace_impl_no_rehash(a);
|
||||
a.create_node();
|
||||
node_tmp b(
|
||||
boost::unordered::detail::func::construct_value(a, *i),
|
||||
a.alloc_);
|
||||
emplace_impl_no_rehash(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -513,8 +524,11 @@ namespace boost { namespace unordered { namespace detail {
|
||||
{
|
||||
node_constructor a(this->node_alloc());
|
||||
for (; i != j; ++i) {
|
||||
a.construct_with_value2(*i);
|
||||
emplace_impl(a);
|
||||
a.create_node();
|
||||
node_tmp b(
|
||||
boost::unordered::detail::func::construct_value(a, *i),
|
||||
a.alloc_);
|
||||
emplace_impl(b);
|
||||
}
|
||||
}
|
||||
|
||||
@ -635,12 +649,16 @@ namespace boost { namespace unordered { namespace detail {
|
||||
for (iterator n = src.begin(); n.node_;) {
|
||||
std::size_t key_hash = n.node_->hash_;
|
||||
iterator group_end(n.node_->group_prev_->next_);
|
||||
constructor.construct_with_value2(*n);
|
||||
iterator pos = this->add_node(constructor, key_hash, iterator());
|
||||
constructor.create_node();
|
||||
iterator pos = this->add_node(
|
||||
boost::unordered::detail::func::construct_value(
|
||||
constructor, *n), key_hash, iterator());
|
||||
for (++n; n != group_end; ++n)
|
||||
{
|
||||
constructor.construct_with_value2(*n);
|
||||
this->add_node(constructor, key_hash, pos);
|
||||
constructor.create_node();
|
||||
this->add_node(
|
||||
boost::unordered::detail::func::construct_value(
|
||||
constructor, *n), key_hash, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -652,12 +670,16 @@ namespace boost { namespace unordered { namespace detail {
|
||||
for (iterator n = src.begin(); n.node_;) {
|
||||
std::size_t key_hash = n.node_->hash_;
|
||||
iterator group_end(n.node_->group_prev_->next_);
|
||||
constructor.construct_with_value2(boost::move(*n));
|
||||
iterator pos = this->add_node(constructor, key_hash, iterator());
|
||||
constructor.create_node();
|
||||
iterator pos = this->add_node(
|
||||
boost::unordered::detail::func::construct_value(
|
||||
constructor, boost::move(*n)), key_hash, iterator());
|
||||
for (++n; n != group_end; ++n)
|
||||
{
|
||||
constructor.construct_with_value2(boost::move(*n));
|
||||
this->add_node(constructor, key_hash, pos);
|
||||
constructor.create_node();
|
||||
this->add_node(
|
||||
boost::unordered::detail::func::construct_value(
|
||||
constructor, boost::move(*n)), key_hash, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,6 +111,8 @@ namespace boost { namespace unordered { namespace detail {
|
||||
bucket_pointer;
|
||||
typedef boost::unordered::detail::node_constructor<node_allocator>
|
||||
node_constructor;
|
||||
typedef boost::unordered::detail::node_tmp<node_allocator>
|
||||
node_tmp;
|
||||
|
||||
typedef boost::unordered::iterator_detail::
|
||||
iterator<node> iterator;
|
||||
@ -366,7 +368,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
else if (bucket::extra_node)
|
||||
{
|
||||
node_constructor a(node_alloc());
|
||||
a.construct();
|
||||
a.create_node();
|
||||
|
||||
(constructor.get() +
|
||||
static_cast<std::ptrdiff_t>(new_count))->next_ =
|
||||
|
@ -190,6 +190,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
typedef typename table::key_equal key_equal;
|
||||
typedef typename table::key_type key_type;
|
||||
typedef typename table::node_constructor node_constructor;
|
||||
typedef typename table::node_tmp node_tmp;
|
||||
typedef typename table::extractor extractor;
|
||||
typedef typename table::iterator iterator;
|
||||
typedef typename table::c_iterator c_iterator;
|
||||
@ -308,7 +309,7 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// Emplace/Insert
|
||||
|
||||
inline iterator add_node(
|
||||
node_constructor& a,
|
||||
node_tmp& a,
|
||||
std::size_t key_hash)
|
||||
{
|
||||
return add_node(a.release(), key_hash);
|
||||
@ -356,13 +357,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(this->node_alloc());
|
||||
a.construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS3(
|
||||
boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(k),
|
||||
boost::make_tuple()));
|
||||
a.create_node();
|
||||
node_tmp b(boost::unordered::detail::func::construct_pair(a, k),
|
||||
a.alloc_);
|
||||
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
return *add_node(a, key_hash);
|
||||
return *add_node(b, key_hash);
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
@ -418,26 +418,33 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// Create the node before rehashing in case it throws an
|
||||
// exception (need strong safety in such a case).
|
||||
node_constructor a(this->node_alloc());
|
||||
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
a.create_node();
|
||||
node_tmp b(
|
||||
boost::unordered::detail::func::construct_value_generic(
|
||||
a, BOOST_UNORDERED_EMPLACE_FORWARD),
|
||||
a.alloc_);
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
return emplace_return(this->add_node(a, key_hash), true);
|
||||
return emplace_return(this->add_node(b, key_hash), true);
|
||||
}
|
||||
|
||||
emplace_return emplace_impl_with_node(node_constructor& a)
|
||||
emplace_return emplace_impl_with_node(node_constructor& a, node_tmp& b)
|
||||
{
|
||||
key_type const& k = this->get_key(a.value());
|
||||
key_type const& k = this->get_key(b.value());
|
||||
std::size_t key_hash = this->hash(k);
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
if (pos.node_) return emplace_return(pos, false);
|
||||
if (pos.node_) {
|
||||
a.reclaim(b.release());
|
||||
return emplace_return(pos, false);
|
||||
}
|
||||
|
||||
// reserve has basic exception safety if the hash function
|
||||
// throws, strong otherwise.
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
return emplace_return(this->add_node(a, key_hash), true);
|
||||
return emplace_return(this->add_node(b, key_hash), true);
|
||||
}
|
||||
|
||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||
@ -446,8 +453,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// Don't have a key, so construct the node first in order
|
||||
// to be able to lookup the position.
|
||||
node_constructor a(this->node_alloc());
|
||||
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||
return emplace_impl_with_node(a);
|
||||
a.create_node();
|
||||
node_tmp b(
|
||||
boost::unordered::detail::func::construct_value_generic(
|
||||
a, BOOST_UNORDERED_EMPLACE_FORWARD),
|
||||
a.alloc_);
|
||||
return emplace_impl_with_node(a, b);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@ -492,13 +503,16 @@ namespace boost { namespace unordered { namespace detail {
|
||||
iterator pos = this->find_node(key_hash, k);
|
||||
|
||||
if (!pos.node_) {
|
||||
a.construct_with_value2(*i);
|
||||
a.create_node();
|
||||
node_tmp b(
|
||||
boost::unordered::detail::func::construct_value(a, *i),
|
||||
a.alloc_);
|
||||
if(this->size_ + 1 > this->max_load_)
|
||||
this->reserve_for_insert(this->size_ +
|
||||
boost::unordered::detail::insert_size(i, j));
|
||||
|
||||
// Nothing after this point can throw.
|
||||
this->add_node(a, key_hash);
|
||||
this->add_node(b, key_hash);
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,8 +522,11 @@ namespace boost { namespace unordered { namespace detail {
|
||||
node_constructor a(this->node_alloc());
|
||||
|
||||
do {
|
||||
a.construct_with_value2(*i);
|
||||
emplace_impl_with_node(a);
|
||||
if (!a.node_) { a.create_node(); }
|
||||
node_tmp b(
|
||||
boost::unordered::detail::func::construct_value(a, *i),
|
||||
a.alloc_);
|
||||
emplace_impl_with_node(a, b);
|
||||
} while(++i != j);
|
||||
}
|
||||
|
||||
@ -587,8 +604,10 @@ namespace boost { namespace unordered { namespace detail {
|
||||
this->create_buckets(this->bucket_count_);
|
||||
|
||||
for(iterator n = src.begin(); n.node_; ++n) {
|
||||
constructor.construct_with_value2(*n);
|
||||
this->add_node(constructor, n.node_->hash_);
|
||||
constructor.create_node();
|
||||
this->add_node(
|
||||
boost::unordered::detail::func::construct_value(
|
||||
constructor, *n), n.node_->hash_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -597,8 +616,10 @@ namespace boost { namespace unordered { namespace detail {
|
||||
this->create_buckets(this->bucket_count_);
|
||||
|
||||
for(iterator n = src.begin(); n.node_; ++n) {
|
||||
constructor.construct_with_value2(boost::move(*n));
|
||||
this->add_node(constructor, n.node_->hash_);
|
||||
constructor.create_node();
|
||||
this->add_node(
|
||||
boost::unordered::detail::func::construct_value(
|
||||
constructor, boost::move(*n)), n.node_->hash_);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user