From 88612a8be44b96a7f8aef17a92ac8349a04a1c01 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 14 Aug 2016 20:55:40 +0100 Subject: [PATCH] Less faffing around with node_constructor. --- include/boost/unordered/detail/allocate.hpp | 45 ++++++--- include/boost/unordered/detail/buckets.hpp | 20 ++-- include/boost/unordered/detail/equivalent.hpp | 45 ++++----- include/boost/unordered/detail/unique.hpp | 92 +++++++++---------- 4 files changed, 103 insertions(+), 99 deletions(-) diff --git a/include/boost/unordered/detail/allocate.hpp b/include/boost/unordered/detail/allocate.hpp index c3b34ce3..710a7a5f 100644 --- a/include/boost/unordered/detail/allocate.hpp +++ b/include/boost/unordered/detail/allocate.hpp @@ -1199,40 +1199,55 @@ namespace boost { namespace unordered { namespace detail { namespace func { // Some nicer construct_value functions, might try to // improve implementation later. - template - inline typename AllocAndPointer::node_pointer construct_value_generic(AllocAndPointer& a, BOOST_UNORDERED_EMPLACE_ARGS) { - construct_value_impl(a.alloc_, a.node_->value_ptr(), + template + inline typename boost::unordered::detail::allocator_traits::pointer + construct_value_generic(Alloc& alloc, BOOST_UNORDERED_EMPLACE_ARGS) + { + node_constructor a(alloc); + a.create_node(); + construct_value_impl(alloc, a.node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD); return a.release(); } - template - inline typename AllocAndPointer::node_pointer construct_value(AllocAndPointer& a, BOOST_FWD_REF(U) x) { + template + inline typename boost::unordered::detail::allocator_traits::pointer + construct_value(Alloc& alloc, BOOST_FWD_REF(U) x) + { + node_constructor a(alloc); + a.create_node(); boost::unordered::detail::func::call_construct( - a.alloc_, a.node_->value_ptr(), boost::forward(x)); + alloc, a.node_->value_ptr(), boost::forward(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 - inline typename AllocAndPointer::node_pointer construct_pair(AllocAndPointer& a, BOOST_FWD_REF(Key) k) { + template + inline typename boost::unordered::detail::allocator_traits::pointer + construct_pair(Alloc& alloc, BOOST_FWD_REF(Key) k) + { + node_constructor a(alloc); + a.create_node(); boost::unordered::detail::func::call_construct( - a.alloc_, boost::addressof(a.node_->value_ptr()->first), + alloc, boost::addressof(a.node_->value_ptr()->first), boost::forward(k)); boost::unordered::detail::func::call_construct( - a.alloc_, boost::addressof(a.node_->value_ptr()->second)); + alloc, boost::addressof(a.node_->value_ptr()->second)); return a.release(); } - template - inline typename AllocAndPointer::node_pointer construct_pair(AllocAndPointer& a, - BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m) { + template + inline typename boost::unordered::detail::allocator_traits::pointer + construct_pair(Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m) + { + node_constructor a(alloc); + a.create_node(); boost::unordered::detail::func::call_construct( - a.alloc_, boost::addressof(a.node_->value_ptr()->first), + alloc, boost::addressof(a.node_->value_ptr()->first), boost::forward(k)); boost::unordered::detail::func::call_construct( - a.alloc_, boost::addressof(a.node_->value_ptr()->second), + alloc, boost::addressof(a.node_->value_ptr()->second), boost::forward(m)); return a.release(); } diff --git a/include/boost/unordered/detail/buckets.hpp b/include/boost/unordered/detail/buckets.hpp index 24257ea8..d7cc170b 100644 --- a/include/boost/unordered/detail/buckets.hpp +++ b/include/boost/unordered/detail/buckets.hpp @@ -374,7 +374,9 @@ namespace boost { namespace unordered { namespace detail { } else { constructor_.create_node(); - return boost::unordered::detail::func::construct_value(constructor_, v); + boost::unordered::detail::func::call_construct( + constructor_.alloc_, constructor_.node_->value_ptr(), v); + return constructor_.release(); } } @@ -386,7 +388,9 @@ namespace boost { namespace unordered { namespace detail { else { constructor_.create_node(); } - return boost::unordered::detail::func::construct_value(constructor_, v); + boost::unordered::detail::func::call_construct( + constructor_.alloc_, constructor_.node_->value_ptr(), v); + return constructor_.release(); } template @@ -398,8 +402,10 @@ namespace boost { namespace unordered { namespace detail { } else { constructor_.create_node(); - return boost::unordered::detail::func::construct_value( - constructor_, boost::move(v)); + boost::unordered::detail::func::call_construct( + constructor_.alloc_, constructor_.node_->value_ptr(), + boost::move(v)); + return constructor_.release(); } } @@ -411,8 +417,10 @@ namespace boost { namespace unordered { namespace detail { else { constructor_.create_node(); } - return boost::unordered::detail::func::construct_value( - constructor_, boost::move(v)); + boost::unordered::detail::func::call_construct( + constructor_.alloc_, constructor_.node_->value_ptr(), + boost::move(v)); + return constructor_.release(); } iterator begin() const diff --git a/include/boost/unordered/detail/equivalent.hpp b/include/boost/unordered/detail/equivalent.hpp index 4d5c0f36..ea8d34d9 100644 --- a/include/boost/unordered/detail/equivalent.hpp +++ b/include/boost/unordered/detail/equivalent.hpp @@ -473,11 +473,10 @@ namespace boost { namespace unordered { namespace detail { template iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS) { - node_constructor a(this->node_alloc()); - a.create_node(); node_tmp b( - boost::unordered::detail::func::construct_value_generic(a, BOOST_UNORDERED_EMPLACE_FORWARD), - a.alloc_); + boost::unordered::detail::func::construct_value_generic( + this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD), + this->node_alloc()); return iterator(emplace_impl(b)); } @@ -495,24 +494,21 @@ namespace boost { namespace unordered { namespace detail { std::size_t distance = std::distance(i, j); if(distance == 1) { - node_constructor a(this->node_alloc()); - a.create_node(); node_tmp b( - boost::unordered::detail::func::construct_value(a, *i), - a.alloc_); - + boost::unordered::detail::func::construct_value( + this->node_alloc(), *i), + this->node_alloc()); emplace_impl(b); } else { // Only require basic exception safety here this->reserve_for_insert(this->size_ + distance); - node_constructor a(this->node_alloc()); for (; i != j; ++i) { - a.create_node(); node_tmp b( - boost::unordered::detail::func::construct_value(a, *i), - a.alloc_); + boost::unordered::detail::func::construct_value( + this->node_alloc(), *i), + this->node_alloc()); emplace_impl_no_rehash(b); } } @@ -522,12 +518,11 @@ namespace boost { namespace unordered { namespace detail { void insert_range(I i, I j, typename boost::unordered::detail::disable_if_forward::type = 0) { - node_constructor a(this->node_alloc()); for (; i != j; ++i) { - a.create_node(); node_tmp b( - boost::unordered::detail::func::construct_value(a, *i), - a.alloc_); + boost::unordered::detail::func::construct_value( + this->node_alloc(), *i), + this->node_alloc()); emplace_impl(b); } } @@ -643,43 +638,37 @@ namespace boost { namespace unordered { namespace detail { // fill_buckets void copy_buckets(table const& src) { - node_constructor constructor(this->node_alloc()); this->create_buckets(this->bucket_count_); for (iterator n = src.begin(); n.node_;) { std::size_t key_hash = n.node_->hash_; iterator group_end(n.node_->group_prev_->next_); - constructor.create_node(); iterator pos = this->add_node( boost::unordered::detail::func::construct_value( - constructor, *n), key_hash, iterator()); + this->node_alloc(), *n), key_hash, iterator()); for (++n; n != group_end; ++n) { - constructor.create_node(); this->add_node( boost::unordered::detail::func::construct_value( - constructor, *n), key_hash, pos); + this->node_alloc(), *n), key_hash, pos); } } } - void move_buckets(table& src) { - node_constructor constructor(this->node_alloc()); + void move_buckets(table const& src) { this->create_buckets(this->bucket_count_); for (iterator n = src.begin(); n.node_;) { std::size_t key_hash = n.node_->hash_; iterator group_end(n.node_->group_prev_->next_); - constructor.create_node(); iterator pos = this->add_node( boost::unordered::detail::func::construct_value( - constructor, boost::move(*n)), key_hash, iterator()); + this->node_alloc(), boost::move(*n)), key_hash, iterator()); for (++n; n != group_end; ++n) { - constructor.create_node(); this->add_node( boost::unordered::detail::func::construct_value( - constructor, boost::move(*n)), key_hash, pos); + this->node_alloc(), boost::move(*n)), key_hash, pos); } } } diff --git a/include/boost/unordered/detail/unique.hpp b/include/boost/unordered/detail/unique.hpp index d1012924..1ec71aef 100644 --- a/include/boost/unordered/detail/unique.hpp +++ b/include/boost/unordered/detail/unique.hpp @@ -356,10 +356,9 @@ 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.create_node(); - node_tmp b(boost::unordered::detail::func::construct_pair(a, k), - a.alloc_); + node_tmp b( + boost::unordered::detail::func::construct_pair(this->node_alloc(), k), + this->node_alloc()); this->reserve_for_insert(this->size_ + 1); return *add_node(b, key_hash); @@ -417,12 +416,10 @@ 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.create_node(); node_tmp b( boost::unordered::detail::func::construct_value_generic( - a, BOOST_UNORDERED_EMPLACE_FORWARD), - a.alloc_); + this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD), + this->node_alloc()); // reserve has basic exception safety if the hash function // throws, strong otherwise. @@ -430,35 +427,25 @@ namespace boost { namespace unordered { namespace detail { return emplace_return(this->add_node(b, key_hash), true); } - emplace_return emplace_impl_with_node(node_constructor& a, node_tmp& b) - { - 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_) { - 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(b, key_hash), true); - } - template emplace_return emplace_impl(no_key, BOOST_UNORDERED_EMPLACE_ARGS) { // 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.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); + this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD), + this->node_alloc()); + 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); } + + // 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(b, key_hash), true); } //////////////////////////////////////////////////////////////////////// @@ -477,9 +464,7 @@ namespace boost { namespace unordered { namespace detail { template void insert_range_impl(key_type const& k, InputIt i, InputIt j) { - node_constructor a(this->node_alloc()); - - insert_range_impl2(a, k, i, j); + insert_range_impl2(k, i, j); while(++i != j) { // Note: can't use get_key as '*i' might not be value_type - it @@ -490,23 +475,21 @@ namespace boost { namespace unordered { namespace detail { // key here. Could be more efficient if '*i' is expensive. Could // be less efficient if copying the full value_type is // expensive. - insert_range_impl2(a, extractor::extract(*i), i, j); + insert_range_impl2(extractor::extract(*i), i, j); } } template - void insert_range_impl2(node_constructor& a, key_type const& k, - InputIt i, InputIt j) + void insert_range_impl2(key_type const& k, InputIt i, InputIt j) { // No side effects in this initial code std::size_t key_hash = this->hash(k); iterator pos = this->find_node(key_hash, k); if (!pos.node_) { - a.create_node(); node_tmp b( - boost::unordered::detail::func::construct_value(a, *i), - a.alloc_); + boost::unordered::detail::func::construct_value(this->node_alloc(), *i), + this->node_alloc()); if(this->size_ + 1 > this->max_load_) this->reserve_for_insert(this->size_ + boost::unordered::detail::insert_size(i, j)); @@ -523,10 +506,23 @@ namespace boost { namespace unordered { namespace detail { do { 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); + boost::unordered::detail::func::call_construct( + a.alloc_, a.node_->value_ptr(), *i); + node_tmp b(a.release(), a.alloc_); + + 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_) { + a.reclaim(b.release()); + } + else { + // reserve has basic exception safety if the hash function + // throws, strong otherwise. + this->reserve_for_insert(this->size_ + 1); + this->add_node(b, key_hash); + } } while(++i != j); } @@ -600,26 +596,22 @@ namespace boost { namespace unordered { namespace detail { // fill_buckets void copy_buckets(table const& src) { - node_constructor constructor(this->node_alloc()); this->create_buckets(this->bucket_count_); for(iterator n = src.begin(); n.node_; ++n) { - constructor.create_node(); this->add_node( boost::unordered::detail::func::construct_value( - constructor, *n), n.node_->hash_); + this->node_alloc(), *n), n.node_->hash_); } } - void move_buckets(table& src) { - node_constructor constructor(this->node_alloc()); + void move_buckets(table const& src) { this->create_buckets(this->bucket_count_); for(iterator n = src.begin(); n.node_; ++n) { - constructor.create_node(); this->add_node( boost::unordered::detail::func::construct_value( - constructor, boost::move(*n)), n.node_->hash_); + this->node_alloc(), boost::move(*n)), n.node_->hash_); } }