From bd10a8b5aace7fd19765efb460fec4d6d73a6e2d Mon Sep 17 00:00:00 2001 From: Daniel James Date: Thu, 16 May 2013 22:15:42 +0000 Subject: [PATCH] Merge initial unordered use of noexcept + friends. Still more to come, hopefully in time for the release. [SVN r84304] --- include/boost/unordered/detail/buckets.hpp | 85 ++++++++++++++++++++-- include/boost/unordered/detail/table.hpp | 25 +++---- include/boost/unordered/unordered_map.hpp | 72 +++++++++--------- include/boost/unordered/unordered_set.hpp | 72 +++++++++--------- 4 files changed, 160 insertions(+), 94 deletions(-) diff --git a/include/boost/unordered/detail/buckets.hpp b/include/boost/unordered/detail/buckets.hpp index f3602339..65392241 100644 --- a/include/boost/unordered/detail/buckets.hpp +++ b/include/boost/unordered/detail/buckets.hpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include #include @@ -670,12 +672,23 @@ namespace boost { namespace unordered { namespace detail { // atomically assigns the new function objects in a strongly // exception safe manner. - template class set_hash_functions; + template + class set_hash_functions; template class functions { - friend class boost::unordered::detail::set_hash_functions; + public: + static const bool nothrow_move_assignable = + boost::is_nothrow_move_assignable::value && + boost::is_nothrow_move_assignable

::value; + static const bool nothrow_move_constructible = + boost::is_nothrow_move_constructible::value && + boost::is_nothrow_move_constructible

::value; + + private: + friend class boost::unordered::detail::set_hash_functions; functions& operator=(functions const&); typedef compressed function_pair; @@ -692,6 +705,11 @@ namespace boost { namespace unordered { namespace detail { static_cast(&funcs_[current_])); } + function_pair& current() { + return *static_cast( + static_cast(&funcs_[current_])); + } + void construct(bool which, H const& hf, P const& eq) { new((void*) &funcs_[which]) function_pair(hf, eq); @@ -702,6 +720,12 @@ namespace boost { namespace unordered { namespace detail { new((void*) &funcs_[which]) function_pair(f); } + void construct(bool which, function_pair& f, + boost::unordered::detail::move_tag m) + { + new((void*) &funcs_[which]) function_pair(f, m); + } + void destroy(bool which) { boost::unordered::detail::destroy((function_pair*)(&funcs_[which])); @@ -709,6 +733,9 @@ namespace boost { namespace unordered { namespace detail { public: + typedef boost::unordered::detail::set_hash_functions set_hash_functions; + functions(H const& hf, P const& eq) : current_(false) { @@ -721,6 +748,17 @@ namespace boost { namespace unordered { namespace detail { construct(current_, bf.current()); } + functions(functions& bf, boost::unordered::detail::move_tag m) + : current_(false) + { + if (nothrow_move_constructible) { + construct(current_, bf.current(), m); + } + else { + construct(current_, bf.current()); + } + } + ~functions() { this->destroy(current_); } @@ -733,26 +771,28 @@ namespace boost { namespace unordered { namespace detail { return current().second(); } }; - + template - class set_hash_functions + class set_hash_functions { set_hash_functions(set_hash_functions const&); set_hash_functions& operator=(set_hash_functions const&); + + typedef functions functions_type; - functions& functions_; + functions_type& functions_; bool tmp_functions_; public: - set_hash_functions(functions& f, H const& h, P const& p) + set_hash_functions(functions_type& f, H const& h, P const& p) : functions_(f), tmp_functions_(!f.current_) { f.construct(tmp_functions_, h, p); } - set_hash_functions(functions& f, functions const& other) + set_hash_functions(functions_type& f, functions_type const& other) : functions_(f), tmp_functions_(!f.current_) { @@ -771,6 +811,37 @@ namespace boost { namespace unordered { namespace detail { } }; + template + class set_hash_functions + { + set_hash_functions(set_hash_functions const&); + set_hash_functions& operator=(set_hash_functions const&); + + typedef functions functions_type; + + functions_type& functions_; + H hash_; + P pred_; + + public: + + set_hash_functions(functions_type& f, H const& h, P const& p) : + functions_(f), + hash_(h), + pred_(p) {} + + set_hash_functions(functions_type& f, functions_type const& other) : + functions_(f), + hash_(other.hash_function()), + pred_(other.key_eq()) {} + + void commit() + { + functions_.current().first() = boost::move(hash_); + functions_.current().second() = boost::move(pred_); + } + }; + //////////////////////////////////////////////////////////////////////////// // rvalue parameters when type can't be a BOOST_RV_REF(T) parameter // e.g. for int diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index a0b14c0c..84d1183d 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -159,6 +159,7 @@ namespace boost { namespace unordered { namespace detail { typedef boost::unordered::detail::functions< typename Types::hasher, typename Types::key_equal> functions; + typedef typename functions::set_hash_functions set_hash_functions; typedef typename Types::allocator allocator; typedef typename boost::unordered::detail:: @@ -363,7 +364,7 @@ namespace boost { namespace unordered { namespace detail { {} table(table& x, boost::unordered::detail::move_tag m) : - functions(x), + functions(x, m), allocators_(x.allocators_, m), bucket_count_(x.bucket_count_), size_(x.size_), @@ -377,8 +378,8 @@ namespace boost { namespace unordered { namespace detail { } table(table& x, node_allocator const& a, - boost::unordered::detail::move_tag) : - functions(x), + boost::unordered::detail::move_tag m) : + functions(x, m), allocators_(a, a), bucket_count_(x.bucket_count_), size_(0), @@ -469,10 +470,8 @@ namespace boost { namespace unordered { namespace detail { // Only swaps the allocators if propagate_on_container_swap void swap(table& x) { - boost::unordered::detail::set_hash_functions - op1(*this, x); - boost::unordered::detail::set_hash_functions - op2(x, *this); + set_hash_functions op1(*this, x); + set_hash_functions op2(x, *this); // I think swap can throw if Propagate::value, // since the allocators' swap can throw. Not sure though. @@ -637,8 +636,7 @@ namespace boost { namespace unordered { namespace detail { void assign(table const& x, false_type) { // Strong exception safety. - boost::unordered::detail::set_hash_functions - new_func_this(*this, x); + set_hash_functions new_func_this(*this, x); new_func_this.commit(); mlf_ = x.mlf_; recalculate_max_load(); @@ -666,8 +664,7 @@ namespace boost { namespace unordered { namespace detail { assign(x, false_type()); } else { - boost::unordered::detail::set_hash_functions - new_func_this(*this, x); + set_hash_functions new_func_this(*this, x); // Delete everything with current allocators before assigning // the new ones. @@ -714,8 +711,7 @@ namespace boost { namespace unordered { namespace detail { move_assign_no_alloc(x); } else { - boost::unordered::detail::set_hash_functions - new_func_this(*this, x); + set_hash_functions new_func_this(*this, x); new_func_this.commit(); mlf_ = x.mlf_; recalculate_max_load(); @@ -740,8 +736,7 @@ namespace boost { namespace unordered { namespace detail { void move_assign_no_alloc(table& x) { - boost::unordered::detail::set_hash_functions - new_func_this(*this, x); + set_hash_functions new_func_this(*this, x); // No throw from here. mlf_ = x.mlf_; max_load_ = x.max_load_; diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index 33449d9c..682e3544 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -178,53 +178,53 @@ namespace unordered unordered_map& operator=(std::initializer_list); #endif - allocator_type get_allocator() const + allocator_type get_allocator() const BOOST_NOEXCEPT { return table_.node_alloc(); } // size and capacity - bool empty() const + bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; } - size_type size() const + size_type size() const BOOST_NOEXCEPT { return table_.size_; } - size_type max_size() const; + size_type max_size() const BOOST_NOEXCEPT; // iterators - iterator begin() + iterator begin() BOOST_NOEXCEPT { return table_.begin(); } - const_iterator begin() const + const_iterator begin() const BOOST_NOEXCEPT { return table_.begin(); } - iterator end() + iterator end() BOOST_NOEXCEPT { return iterator(); } - const_iterator end() const + const_iterator end() const BOOST_NOEXCEPT { return const_iterator(); } - const_iterator cbegin() const + const_iterator cbegin() const BOOST_NOEXCEPT { return table_.begin(); } - const_iterator cend() const + const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); } @@ -449,12 +449,12 @@ namespace unordered // bucket interface - size_type bucket_count() const + size_type bucket_count() const BOOST_NOEXCEPT { return table_.bucket_count_; } - size_type max_bucket_count() const + size_type max_bucket_count() const BOOST_NOEXCEPT { return table_.max_bucket_count(); } @@ -501,13 +501,13 @@ namespace unordered // hash policy - float max_load_factor() const + float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; } - float load_factor() const; - void max_load_factor(float); + float load_factor() const BOOST_NOEXCEPT; + void max_load_factor(float) BOOST_NOEXCEPT; void rehash(size_type); void reserve(size_type); @@ -660,53 +660,53 @@ namespace unordered unordered_multimap& operator=(std::initializer_list); #endif - allocator_type get_allocator() const + allocator_type get_allocator() const BOOST_NOEXCEPT { return table_.node_alloc(); } // size and capacity - bool empty() const + bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; } - size_type size() const + size_type size() const BOOST_NOEXCEPT { return table_.size_; } - size_type max_size() const; + size_type max_size() const BOOST_NOEXCEPT; // iterators - iterator begin() + iterator begin() BOOST_NOEXCEPT { return table_.begin(); } - const_iterator begin() const + const_iterator begin() const BOOST_NOEXCEPT { return table_.begin(); } - iterator end() + iterator end() BOOST_NOEXCEPT { return iterator(); } - const_iterator end() const + const_iterator end() const BOOST_NOEXCEPT { return const_iterator(); } - const_iterator cbegin() const + const_iterator cbegin() const BOOST_NOEXCEPT { return table_.begin(); } - const_iterator cend() const + const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); } @@ -927,12 +927,12 @@ namespace unordered // bucket interface - size_type bucket_count() const + size_type bucket_count() const BOOST_NOEXCEPT { return table_.bucket_count_; } - size_type max_bucket_count() const + size_type max_bucket_count() const BOOST_NOEXCEPT { return table_.max_bucket_count(); } @@ -979,13 +979,13 @@ namespace unordered // hash policy - float max_load_factor() const + float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; } - float load_factor() const; - void max_load_factor(float); + float load_factor() const BOOST_NOEXCEPT; + void max_load_factor(float) BOOST_NOEXCEPT; void rehash(size_type); void reserve(size_type); @@ -1105,7 +1105,7 @@ namespace unordered // size and capacity template - std::size_t unordered_map::max_size() const + std::size_t unordered_map::max_size() const BOOST_NOEXCEPT { return table_.max_size(); } @@ -1274,13 +1274,13 @@ namespace unordered // hash policy template - float unordered_map::load_factor() const + float unordered_map::load_factor() const BOOST_NOEXCEPT { return table_.load_factor(); } template - void unordered_map::max_load_factor(float m) + void unordered_map::max_load_factor(float m) BOOST_NOEXCEPT { table_.max_load_factor(m); } @@ -1438,7 +1438,7 @@ namespace unordered // size and capacity template - std::size_t unordered_multimap::max_size() const + std::size_t unordered_multimap::max_size() const BOOST_NOEXCEPT { return table_.max_size(); } @@ -1586,13 +1586,13 @@ namespace unordered // hash policy template - float unordered_multimap::load_factor() const + float unordered_multimap::load_factor() const BOOST_NOEXCEPT { return table_.load_factor(); } template - void unordered_multimap::max_load_factor(float m) + void unordered_multimap::max_load_factor(float m) BOOST_NOEXCEPT { table_.max_load_factor(m); } diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index 6787a3a3..0ccf1b94 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -176,53 +176,53 @@ namespace unordered unordered_set& operator=(std::initializer_list); #endif - allocator_type get_allocator() const + allocator_type get_allocator() const BOOST_NOEXCEPT { return table_.node_alloc(); } // size and capacity - bool empty() const + bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; } - size_type size() const + size_type size() const BOOST_NOEXCEPT { return table_.size_; } - size_type max_size() const; + size_type max_size() const BOOST_NOEXCEPT; // iterators - iterator begin() + iterator begin() BOOST_NOEXCEPT { return table_.begin(); } - const_iterator begin() const + const_iterator begin() const BOOST_NOEXCEPT { return table_.begin(); } - iterator end() + iterator end() BOOST_NOEXCEPT { return iterator(); } - const_iterator end() const + const_iterator end() const BOOST_NOEXCEPT { return const_iterator(); } - const_iterator cbegin() const + const_iterator cbegin() const BOOST_NOEXCEPT { return table_.begin(); } - const_iterator cend() const + const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); } @@ -434,12 +434,12 @@ namespace unordered // bucket interface - size_type bucket_count() const + size_type bucket_count() const BOOST_NOEXCEPT { return table_.bucket_count_; } - size_type max_bucket_count() const + size_type max_bucket_count() const BOOST_NOEXCEPT { return table_.max_bucket_count(); } @@ -486,13 +486,13 @@ namespace unordered // hash policy - float max_load_factor() const + float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; } - float load_factor() const; - void max_load_factor(float); + float load_factor() const BOOST_NOEXCEPT; + void max_load_factor(float) BOOST_NOEXCEPT; void rehash(size_type); void reserve(size_type); @@ -644,53 +644,53 @@ namespace unordered unordered_multiset& operator=(std::initializer_list); #endif - allocator_type get_allocator() const + allocator_type get_allocator() const BOOST_NOEXCEPT { return table_.node_alloc(); } // size and capacity - bool empty() const + bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; } - size_type size() const + size_type size() const BOOST_NOEXCEPT { return table_.size_; } - size_type max_size() const; + size_type max_size() const BOOST_NOEXCEPT; // iterators - iterator begin() + iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); } - const_iterator begin() const + const_iterator begin() const BOOST_NOEXCEPT { return const_iterator(table_.begin()); } - iterator end() + iterator end() BOOST_NOEXCEPT { return iterator(); } - const_iterator end() const + const_iterator end() const BOOST_NOEXCEPT { return const_iterator(); } - const_iterator cbegin() const + const_iterator cbegin() const BOOST_NOEXCEPT { return const_iterator(table_.begin()); } - const_iterator cend() const + const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); } @@ -902,12 +902,12 @@ namespace unordered // bucket interface - size_type bucket_count() const + size_type bucket_count() const BOOST_NOEXCEPT { return table_.bucket_count_; } - size_type max_bucket_count() const + size_type max_bucket_count() const BOOST_NOEXCEPT { return table_.max_bucket_count(); } @@ -954,13 +954,13 @@ namespace unordered // hash policy - float max_load_factor() const + float max_load_factor() const BOOST_NOEXCEPT { return table_.mlf_; } - float load_factor() const; - void max_load_factor(float); + float load_factor() const BOOST_NOEXCEPT; + void max_load_factor(float) BOOST_NOEXCEPT; void rehash(size_type); void reserve(size_type); @@ -1080,7 +1080,7 @@ namespace unordered // size and capacity template - std::size_t unordered_set::max_size() const + std::size_t unordered_set::max_size() const BOOST_NOEXCEPT { return table_.max_size(); } @@ -1200,13 +1200,13 @@ namespace unordered // hash policy template - float unordered_set::load_factor() const + float unordered_set::load_factor() const BOOST_NOEXCEPT { return table_.load_factor(); } template - void unordered_set::max_load_factor(float m) + void unordered_set::max_load_factor(float m) BOOST_NOEXCEPT { table_.max_load_factor(m); } @@ -1364,7 +1364,7 @@ namespace unordered // size and capacity template - std::size_t unordered_multiset::max_size() const + std::size_t unordered_multiset::max_size() const BOOST_NOEXCEPT { return table_.max_size(); } @@ -1484,13 +1484,13 @@ namespace unordered // hash policy template - float unordered_multiset::load_factor() const + float unordered_multiset::load_factor() const BOOST_NOEXCEPT { return table_.load_factor(); } template - void unordered_multiset::max_load_factor(float m) + void unordered_multiset::max_load_factor(float m) BOOST_NOEXCEPT { table_.max_load_factor(m); }