775 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			775 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | 
 | ||
|  | // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard. | ||
|  | // Copyright (C) 2005-2011 Daniel James | ||
|  | // Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
|  | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|  | 
 | ||
|  | #ifndef BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED | ||
|  | #define BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED | ||
|  | 
 | ||
|  | #include <boost/config.hpp> | ||
|  | #if defined(BOOST_HAS_PRAGMA_ONCE) | ||
|  | #pragma once | ||
|  | #endif | ||
|  | 
 | ||
|  | #include <boost/unordered/detail/util.hpp> | ||
|  | #include <boost/unordered/detail/allocate.hpp> | ||
|  | 
 | ||
|  | namespace boost { namespace unordered { namespace detail { | ||
|  | 
 | ||
|  |     template <typename Types> struct table; | ||
|  |     template <typename NodePointer> struct bucket; | ||
|  |     struct ptr_bucket; | ||
|  |     template <typename Types> struct table_impl; | ||
|  |     template <typename Types> struct grouped_table_impl; | ||
|  | 
 | ||
|  | }}} | ||
|  | 
 | ||
|  | // The 'iterator_detail' namespace was a misguided attempt at avoiding ADL | ||
|  | // in the detail namespace. It didn't work because the template parameters | ||
|  | // were in detail. I'm not changing it at the moment to be safe. I might | ||
|  | // do in the future if I change the iterator types. | ||
|  | namespace boost { namespace unordered { namespace iterator_detail { | ||
|  | 
 | ||
|  |     //////////////////////////////////////////////////////////////////////////// | ||
|  |     // Iterators | ||
|  |     // | ||
|  |     // all no throw | ||
|  | 
 | ||
|  |     template <typename Node> struct iterator; | ||
|  |     template <typename Node> struct c_iterator; | ||
|  |     template <typename Node, typename Policy> struct l_iterator; | ||
|  |     template <typename Node, typename Policy> | ||
|  |         struct cl_iterator; | ||
|  | 
 | ||
|  |     // Local Iterators | ||
|  |     // | ||
|  |     // all no throw | ||
|  | 
 | ||
|  |     template <typename Node, typename Policy> | ||
|  |     struct l_iterator | ||
|  |         : public std::iterator< | ||
|  |             std::forward_iterator_tag, | ||
|  |             typename Node::value_type, | ||
|  |             std::ptrdiff_t, | ||
|  |             typename Node::value_type*, | ||
|  |             typename Node::value_type&> | ||
|  |     { | ||
|  | #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) | ||
|  |         template <typename Node2, typename Policy2> | ||
|  |         friend struct boost::unordered::iterator_detail::cl_iterator; | ||
|  |     private: | ||
|  | #endif | ||
|  |         typedef typename Node::node_pointer node_pointer; | ||
|  |         node_pointer ptr_; | ||
|  |         std::size_t bucket_; | ||
|  |         std::size_t bucket_count_; | ||
|  | 
 | ||
|  |     public: | ||
|  | 
 | ||
|  |         typedef typename Node::value_type value_type; | ||
|  | 
 | ||
|  |         l_iterator() BOOST_NOEXCEPT : ptr_() {} | ||
|  | 
 | ||
|  |         l_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT | ||
|  |             : ptr_(n), bucket_(b), bucket_count_(c) {} | ||
|  | 
 | ||
|  |         value_type& operator*() const { | ||
|  |             return ptr_->value(); | ||
|  |         } | ||
|  | 
 | ||
|  |         value_type* operator->() const { | ||
|  |             return ptr_->value_ptr(); | ||
|  |         } | ||
|  | 
 | ||
|  |         l_iterator& operator++() { | ||
|  |             ptr_ = static_cast<node_pointer>(ptr_->next_); | ||
|  |             if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) | ||
|  |                     != bucket_) | ||
|  |                 ptr_ = node_pointer(); | ||
|  |             return *this; | ||
|  |         } | ||
|  | 
 | ||
|  |         l_iterator operator++(int) { | ||
|  |             l_iterator tmp(*this); | ||
|  |             ++(*this); | ||
|  |             return tmp; | ||
|  |         } | ||
|  | 
 | ||
|  |         bool operator==(l_iterator x) const BOOST_NOEXCEPT { | ||
|  |             return ptr_ == x.ptr_; | ||
|  |         } | ||
|  | 
 | ||
|  |         bool operator!=(l_iterator x) const BOOST_NOEXCEPT { | ||
|  |             return ptr_ != x.ptr_; | ||
|  |         } | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <typename Node, typename Policy> | ||
|  |     struct cl_iterator | ||
|  |         : public std::iterator< | ||
|  |             std::forward_iterator_tag, | ||
|  |             typename Node::value_type, | ||
|  |             std::ptrdiff_t, | ||
|  |             typename Node::value_type const*, | ||
|  |             typename Node::value_type const&> | ||
|  |     { | ||
|  |         friend struct boost::unordered::iterator_detail::l_iterator | ||
|  |             <Node, Policy>; | ||
|  |     private: | ||
|  | 
 | ||
|  |         typedef typename Node::node_pointer node_pointer; | ||
|  |         node_pointer ptr_; | ||
|  |         std::size_t bucket_; | ||
|  |         std::size_t bucket_count_; | ||
|  | 
 | ||
|  |     public: | ||
|  | 
 | ||
|  |         typedef typename Node::value_type value_type; | ||
|  | 
 | ||
|  |         cl_iterator() BOOST_NOEXCEPT : ptr_() {} | ||
|  | 
 | ||
|  |         cl_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT : | ||
|  |             ptr_(n), bucket_(b), bucket_count_(c) {} | ||
|  | 
 | ||
|  |         cl_iterator(boost::unordered::iterator_detail::l_iterator< | ||
|  |                 Node, Policy> const& x) BOOST_NOEXCEPT : | ||
|  |             ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_) | ||
|  |         {} | ||
|  | 
 | ||
|  |         value_type const& operator*() const { | ||
|  |             return ptr_->value(); | ||
|  |         } | ||
|  | 
 | ||
|  |         value_type const* operator->() const { | ||
|  |             return ptr_->value_ptr(); | ||
|  |         } | ||
|  | 
 | ||
|  |         cl_iterator& operator++() { | ||
|  |             ptr_ = static_cast<node_pointer>(ptr_->next_); | ||
|  |             if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) | ||
|  |                     != bucket_) | ||
|  |                 ptr_ = node_pointer(); | ||
|  |             return *this; | ||
|  |         } | ||
|  | 
 | ||
|  |         cl_iterator operator++(int) { | ||
|  |             cl_iterator tmp(*this); | ||
|  |             ++(*this); | ||
|  |             return tmp; | ||
|  |         } | ||
|  | 
 | ||
|  |         friend bool operator==(cl_iterator const& x, cl_iterator const& y) | ||
|  |             BOOST_NOEXCEPT | ||
|  |         { | ||
|  |             return x.ptr_ == y.ptr_; | ||
|  |         } | ||
|  | 
 | ||
|  |         friend bool operator!=(cl_iterator const& x, cl_iterator const& y) | ||
|  |             BOOST_NOEXCEPT | ||
|  |         { | ||
|  |             return x.ptr_ != y.ptr_; | ||
|  |         } | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <typename Node> | ||
|  |     struct iterator | ||
|  |         : public std::iterator< | ||
|  |             std::forward_iterator_tag, | ||
|  |             typename Node::value_type, | ||
|  |             std::ptrdiff_t, | ||
|  |             typename Node::value_type*, | ||
|  |             typename Node::value_type&> | ||
|  |     { | ||
|  | #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) | ||
|  |         template <typename> | ||
|  |         friend struct boost::unordered::iterator_detail::c_iterator; | ||
|  |         template <typename> | ||
|  |         friend struct boost::unordered::detail::table; | ||
|  |         template <typename> | ||
|  |         friend struct boost::unordered::detail::table_impl; | ||
|  |         template <typename> | ||
|  |         friend struct boost::unordered::detail::grouped_table_impl; | ||
|  |     private: | ||
|  | #endif | ||
|  |         typedef typename Node::node_pointer node_pointer; | ||
|  |         node_pointer node_; | ||
|  | 
 | ||
|  |     public: | ||
|  | 
 | ||
|  |         typedef typename Node::value_type value_type; | ||
|  | 
 | ||
|  |         iterator() BOOST_NOEXCEPT : node_() {} | ||
|  | 
 | ||
|  |         explicit iterator(typename Node::link_pointer x) BOOST_NOEXCEPT : | ||
|  |             node_(static_cast<node_pointer>(x)) {} | ||
|  | 
 | ||
|  |         value_type& operator*() const { | ||
|  |             return node_->value(); | ||
|  |         } | ||
|  | 
 | ||
|  |         value_type* operator->() const { | ||
|  |             return node_->value_ptr(); | ||
|  |         } | ||
|  | 
 | ||
|  |         iterator& operator++() { | ||
|  |             node_ = static_cast<node_pointer>(node_->next_); | ||
|  |             return *this; | ||
|  |         } | ||
|  | 
 | ||
|  |         iterator operator++(int) { | ||
|  |             iterator tmp(node_); | ||
|  |             node_ = static_cast<node_pointer>(node_->next_); | ||
|  |             return tmp; | ||
|  |         } | ||
|  | 
 | ||
|  |         bool operator==(iterator const& x) const BOOST_NOEXCEPT { | ||
|  |             return node_ == x.node_; | ||
|  |         } | ||
|  | 
 | ||
|  |         bool operator!=(iterator const& x) const BOOST_NOEXCEPT { | ||
|  |             return node_ != x.node_; | ||
|  |         } | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <typename Node> | ||
|  |     struct c_iterator | ||
|  |         : public std::iterator< | ||
|  |             std::forward_iterator_tag, | ||
|  |             typename Node::value_type, | ||
|  |             std::ptrdiff_t, | ||
|  |             typename Node::value_type const*, | ||
|  |             typename Node::value_type const&> | ||
|  |     { | ||
|  |         friend struct boost::unordered::iterator_detail::iterator<Node>; | ||
|  | 
 | ||
|  | #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) | ||
|  |         template <typename> | ||
|  |         friend struct boost::unordered::detail::table; | ||
|  |         template <typename> | ||
|  |         friend struct boost::unordered::detail::table_impl; | ||
|  |         template <typename> | ||
|  |         friend struct boost::unordered::detail::grouped_table_impl; | ||
|  | 
 | ||
|  |     private: | ||
|  | #endif | ||
|  |         typedef typename Node::node_pointer node_pointer; | ||
|  |         typedef boost::unordered::iterator_detail::iterator<Node> n_iterator; | ||
|  |         node_pointer node_; | ||
|  | 
 | ||
|  |     public: | ||
|  | 
 | ||
|  |         typedef typename Node::value_type value_type; | ||
|  | 
 | ||
|  |         c_iterator() BOOST_NOEXCEPT : node_() {} | ||
|  | 
 | ||
|  |         explicit c_iterator(typename Node::link_pointer x) BOOST_NOEXCEPT : | ||
|  |             node_(static_cast<node_pointer>(x)) {} | ||
|  | 
 | ||
|  |         c_iterator(n_iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {} | ||
|  | 
 | ||
|  |         value_type const& operator*() const { | ||
|  |             return node_->value(); | ||
|  |         } | ||
|  | 
 | ||
|  |         value_type const* operator->() const { | ||
|  |             return node_->value_ptr(); | ||
|  |         } | ||
|  | 
 | ||
|  |         c_iterator& operator++() { | ||
|  |             node_ = static_cast<node_pointer>(node_->next_); | ||
|  |             return *this; | ||
|  |         } | ||
|  | 
 | ||
|  |         c_iterator operator++(int) { | ||
|  |             c_iterator tmp(node_); | ||
|  |             node_ = static_cast<node_pointer>(node_->next_); | ||
|  |             return tmp; | ||
|  |         } | ||
|  | 
 | ||
|  |         friend bool operator==(c_iterator const& x, c_iterator const& y) | ||
|  |             BOOST_NOEXCEPT | ||
|  |         { | ||
|  |             return x.node_ == y.node_; | ||
|  |         } | ||
|  | 
 | ||
|  |         friend bool operator!=(c_iterator const& x, c_iterator const& y) | ||
|  |             BOOST_NOEXCEPT | ||
|  |         { | ||
|  |             return x.node_ != y.node_; | ||
|  |         } | ||
|  |     }; | ||
|  | }}} | ||
|  | 
 | ||
|  | namespace boost { namespace unordered { namespace detail { | ||
|  | 
 | ||
|  |     /////////////////////////////////////////////////////////////////// | ||
|  |     // | ||
|  |     // Node Holder | ||
|  |     // | ||
|  |     // Temporary store for nodes. Deletes any that aren't used. | ||
|  | 
 | ||
|  |     template <typename NodeAlloc> | ||
|  |     struct node_holder | ||
|  |     { | ||
|  |     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; | ||
|  |         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) : | ||
|  |             constructor_(b.node_alloc()), | ||
|  |             nodes_() | ||
|  |         { | ||
|  |             if (b.size_) { | ||
|  |                 typename Table::link_pointer prev = b.get_previous_start(); | ||
|  |                 nodes_ = static_cast<node_pointer>(prev->next_); | ||
|  |                 prev->next_ = link_pointer(); | ||
|  |                 b.size_ = 0; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         ~node_holder(); | ||
|  | 
 | ||
|  |         node_pointer pop_node() | ||
|  |         { | ||
|  |             node_pointer n = nodes_; | ||
|  |             nodes_ = static_cast<node_pointer>(nodes_->next_); | ||
|  |             n->init(n); | ||
|  |             n->next_ = link_pointer(); | ||
|  |             return n; | ||
|  |         } | ||
|  | 
 | ||
|  |         template <typename T> | ||
|  |         inline node_pointer copy_of(T const& v) { | ||
|  |             if (nodes_) { | ||
|  |                 constructor_.reclaim(pop_node()); | ||
|  |             } | ||
|  |             else { | ||
|  |                 constructor_.create_node(); | ||
|  |             } | ||
|  |             boost::unordered::detail::func::call_construct( | ||
|  |                 constructor_.alloc_, constructor_.node_->value_ptr(), v); | ||
|  |             return constructor_.release(); | ||
|  |         } | ||
|  | 
 | ||
|  |         template <typename T> | ||
|  |         inline node_pointer move_copy_of(T& v) { | ||
|  |             if (nodes_) { | ||
|  |                 constructor_.reclaim(pop_node()); | ||
|  |             } | ||
|  |             else { | ||
|  |                 constructor_.create_node(); | ||
|  |             } | ||
|  |             boost::unordered::detail::func::call_construct( | ||
|  |                 constructor_.alloc_, constructor_.node_->value_ptr(), | ||
|  |                 boost::move(v)); | ||
|  |             return constructor_.release(); | ||
|  |         } | ||
|  | 
 | ||
|  |         iterator begin() const | ||
|  |         { | ||
|  |             return iterator(nodes_); | ||
|  |         } | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <typename Alloc> | ||
|  |     node_holder<Alloc>::~node_holder() | ||
|  |     { | ||
|  |         while (nodes_) { | ||
|  |             node_pointer p = nodes_; | ||
|  |             nodes_ = static_cast<node_pointer>(p->next_); | ||
|  | 
 | ||
|  |             boost::unordered::detail::func::call_destroy(constructor_.alloc_, | ||
|  |                 p->value_ptr()); | ||
|  |             boost::unordered::detail::func::destroy(boost::addressof(*p)); | ||
|  |             node_allocator_traits::deallocate(constructor_.alloc_, p, 1); | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     /////////////////////////////////////////////////////////////////// | ||
|  |     // | ||
|  |     // Bucket | ||
|  | 
 | ||
|  |     template <typename NodePointer> | ||
|  |     struct bucket | ||
|  |     { | ||
|  |         typedef NodePointer link_pointer; | ||
|  |         link_pointer next_; | ||
|  | 
 | ||
|  |         bucket() : next_() {} | ||
|  | 
 | ||
|  |         link_pointer first_from_start() | ||
|  |         { | ||
|  |             return next_; | ||
|  |         } | ||
|  | 
 | ||
|  |         enum { extra_node = true }; | ||
|  |     }; | ||
|  | 
 | ||
|  |     struct ptr_bucket | ||
|  |     { | ||
|  |         typedef ptr_bucket* link_pointer; | ||
|  |         link_pointer next_; | ||
|  | 
 | ||
|  |         ptr_bucket() : next_(0) {} | ||
|  | 
 | ||
|  |         link_pointer first_from_start() | ||
|  |         { | ||
|  |             return this; | ||
|  |         } | ||
|  | 
 | ||
|  |         enum { extra_node = false }; | ||
|  |     }; | ||
|  | 
 | ||
|  |     /////////////////////////////////////////////////////////////////// | ||
|  |     // | ||
|  |     // Hash Policy | ||
|  | 
 | ||
|  |     template <typename SizeT> | ||
|  |     struct prime_policy | ||
|  |     { | ||
|  |         template <typename Hash, typename T> | ||
|  |         static inline SizeT apply_hash(Hash const& hf, T const& x) { | ||
|  |             return hf(x); | ||
|  |         } | ||
|  | 
 | ||
|  |         static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) { | ||
|  |             return hash % bucket_count; | ||
|  |         } | ||
|  | 
 | ||
|  |         static inline SizeT new_bucket_count(SizeT min) { | ||
|  |             return boost::unordered::detail::next_prime(min); | ||
|  |         } | ||
|  | 
 | ||
|  |         static inline SizeT prev_bucket_count(SizeT max) { | ||
|  |             return boost::unordered::detail::prev_prime(max); | ||
|  |         } | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <typename SizeT> | ||
|  |     struct mix64_policy | ||
|  |     { | ||
|  |         template <typename Hash, typename T> | ||
|  |         static inline SizeT apply_hash(Hash const& hf, T const& x) { | ||
|  |             SizeT key = hf(x); | ||
|  |             key = (~key) + (key << 21); // key = (key << 21) - key - 1; | ||
|  |             key = key ^ (key >> 24); | ||
|  |             key = (key + (key << 3)) + (key << 8); // key * 265 | ||
|  |             key = key ^ (key >> 14); | ||
|  |             key = (key + (key << 2)) + (key << 4); // key * 21 | ||
|  |             key = key ^ (key >> 28); | ||
|  |             key = key + (key << 31); | ||
|  |             return key; | ||
|  |         } | ||
|  | 
 | ||
|  |         static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) { | ||
|  |             return hash & (bucket_count - 1); | ||
|  |         } | ||
|  | 
 | ||
|  |         static inline SizeT new_bucket_count(SizeT min) { | ||
|  |             if (min <= 4) return 4; | ||
|  |             --min; | ||
|  |             min |= min >> 1; | ||
|  |             min |= min >> 2; | ||
|  |             min |= min >> 4; | ||
|  |             min |= min >> 8; | ||
|  |             min |= min >> 16; | ||
|  |             min |= min >> 32; | ||
|  |             return min + 1; | ||
|  |         } | ||
|  | 
 | ||
|  |         static inline SizeT prev_bucket_count(SizeT max) { | ||
|  |             max |= max >> 1; | ||
|  |             max |= max >> 2; | ||
|  |             max |= max >> 4; | ||
|  |             max |= max >> 8; | ||
|  |             max |= max >> 16; | ||
|  |             max |= max >> 32; | ||
|  |             return (max >> 1) + 1; | ||
|  |         } | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <int digits, int radix> | ||
|  |     struct pick_policy_impl { | ||
|  |         typedef prime_policy<std::size_t> type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <> | ||
|  |     struct pick_policy_impl<64, 2> { | ||
|  |         typedef mix64_policy<std::size_t> type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <typename T> | ||
|  |     struct pick_policy : | ||
|  |         pick_policy_impl< | ||
|  |             std::numeric_limits<std::size_t>::digits, | ||
|  |             std::numeric_limits<std::size_t>::radix> {}; | ||
|  | 
 | ||
|  |     // While the mix policy is generally faster, the prime policy is a lot | ||
|  |     // faster when a large number consecutive integers are used, because | ||
|  |     // there are no collisions. Since that is probably quite common, use | ||
|  |     // prime policy for integeral types. But not the smaller ones, as they | ||
|  |     // don't have enough unique values for this to be an issue. | ||
|  | 
 | ||
|  |     template <> | ||
|  |     struct pick_policy<int> { | ||
|  |         typedef prime_policy<std::size_t> type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <> | ||
|  |     struct pick_policy<unsigned int> { | ||
|  |         typedef prime_policy<std::size_t> type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <> | ||
|  |     struct pick_policy<long> { | ||
|  |         typedef prime_policy<std::size_t> type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <> | ||
|  |     struct pick_policy<unsigned long> { | ||
|  |         typedef prime_policy<std::size_t> type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     // TODO: Maybe not if std::size_t is smaller than long long. | ||
|  | #if !defined(BOOST_NO_LONG_LONG) | ||
|  |     template <> | ||
|  |     struct pick_policy<boost::long_long_type> { | ||
|  |         typedef prime_policy<std::size_t> type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <> | ||
|  |     struct pick_policy<boost::ulong_long_type> { | ||
|  |         typedef prime_policy<std::size_t> type; | ||
|  |     }; | ||
|  | #endif | ||
|  | 
 | ||
|  |     //////////////////////////////////////////////////////////////////////////// | ||
|  |     // Functions | ||
|  | 
 | ||
|  |     // Assigning and swapping the equality and hash function objects | ||
|  |     // needs strong exception safety. To implement that normally we'd | ||
|  |     // require one of them to be known to not throw and the other to | ||
|  |     // guarantee strong exception safety. Unfortunately they both only | ||
|  |     // have basic exception safety. So to acheive strong exception | ||
|  |     // safety we have storage space for two copies, and assign the new | ||
|  |     // copies to the unused space. Then switch to using that to use | ||
|  |     // them. This is implemented in 'set_hash_functions' which | ||
|  |     // atomically assigns the new function objects in a strongly | ||
|  |     // exception safe manner. | ||
|  | 
 | ||
|  |     template <class H, class P, bool NoThrowMoveAssign> | ||
|  |     class set_hash_functions; | ||
|  | 
 | ||
|  |     template <class H, class P> | ||
|  |     class functions | ||
|  |     { | ||
|  |     public: | ||
|  |         static const bool nothrow_move_assignable = | ||
|  |                 boost::is_nothrow_move_assignable<H>::value && | ||
|  |                 boost::is_nothrow_move_assignable<P>::value; | ||
|  |         static const bool nothrow_move_constructible = | ||
|  |                 boost::is_nothrow_move_constructible<H>::value && | ||
|  |                 boost::is_nothrow_move_constructible<P>::value; | ||
|  | 
 | ||
|  |     private: | ||
|  |         friend class boost::unordered::detail::set_hash_functions<H, P, | ||
|  |                nothrow_move_assignable>; | ||
|  |         functions& operator=(functions const&); | ||
|  | 
 | ||
|  |         typedef compressed<H, P> function_pair; | ||
|  | 
 | ||
|  |         typedef typename boost::aligned_storage< | ||
|  |             sizeof(function_pair), | ||
|  |             boost::alignment_of<function_pair>::value>::type aligned_function; | ||
|  | 
 | ||
|  |         bool current_; // The currently active functions. | ||
|  |         aligned_function funcs_[2]; | ||
|  | 
 | ||
|  |         function_pair const& current() const { | ||
|  |             return *static_cast<function_pair const*>( | ||
|  |                 static_cast<void const*>(&funcs_[current_])); | ||
|  |         } | ||
|  | 
 | ||
|  |         function_pair& current() { | ||
|  |             return *static_cast<function_pair*>( | ||
|  |                 static_cast<void*>(&funcs_[current_])); | ||
|  |         } | ||
|  | 
 | ||
|  |         void construct(bool which, H const& hf, P const& eq) | ||
|  |         { | ||
|  |             new((void*) &funcs_[which]) function_pair(hf, eq); | ||
|  |         } | ||
|  | 
 | ||
|  |         void construct(bool which, function_pair const& f, | ||
|  |                 boost::unordered::detail::false_type = | ||
|  |                     boost::unordered::detail::false_type()) | ||
|  |         { | ||
|  |             new((void*) &funcs_[which]) function_pair(f); | ||
|  |         } | ||
|  |          | ||
|  |         void construct(bool which, function_pair& f, | ||
|  |                 boost::unordered::detail::true_type) | ||
|  |         { | ||
|  |             new((void*) &funcs_[which]) function_pair(f, | ||
|  |                 boost::unordered::detail::move_tag()); | ||
|  |         } | ||
|  | 
 | ||
|  |         void destroy(bool which) | ||
|  |         { | ||
|  |             boost::unordered::detail::func::destroy((function_pair*)(&funcs_[which])); | ||
|  |         } | ||
|  |          | ||
|  |     public: | ||
|  | 
 | ||
|  |         typedef boost::unordered::detail::set_hash_functions<H, P, | ||
|  |                 nothrow_move_assignable> set_hash_functions; | ||
|  | 
 | ||
|  |         functions(H const& hf, P const& eq) | ||
|  |             : current_(false) | ||
|  |         { | ||
|  |             construct(current_, hf, eq); | ||
|  |         } | ||
|  | 
 | ||
|  |         functions(functions const& bf) | ||
|  |             : current_(false) | ||
|  |         { | ||
|  |             construct(current_, bf.current()); | ||
|  |         } | ||
|  | 
 | ||
|  |         functions(functions& bf, boost::unordered::detail::move_tag) | ||
|  |             : current_(false) | ||
|  |         { | ||
|  |             construct(current_, bf.current(), | ||
|  |                 boost::unordered::detail::integral_constant<bool, | ||
|  |                     nothrow_move_constructible>()); | ||
|  |         } | ||
|  | 
 | ||
|  |         ~functions() { | ||
|  |             this->destroy(current_); | ||
|  |         } | ||
|  | 
 | ||
|  |         H const& hash_function() const { | ||
|  |             return current().first(); | ||
|  |         } | ||
|  | 
 | ||
|  |         P const& key_eq() const { | ||
|  |             return current().second(); | ||
|  |         } | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <class H, class P> | ||
|  |     class set_hash_functions<H, P, false> | ||
|  |     { | ||
|  |         set_hash_functions(set_hash_functions const&); | ||
|  |         set_hash_functions& operator=(set_hash_functions const&); | ||
|  | 
 | ||
|  |         typedef functions<H, P> functions_type; | ||
|  |      | ||
|  |         functions_type& functions_; | ||
|  |         bool tmp_functions_; | ||
|  | 
 | ||
|  |     public: | ||
|  | 
 | ||
|  |         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_type& f, functions_type const& other) | ||
|  |           : functions_(f), | ||
|  |             tmp_functions_(!f.current_) | ||
|  |         { | ||
|  |             f.construct(tmp_functions_, other.current()); | ||
|  |         } | ||
|  | 
 | ||
|  |         ~set_hash_functions() | ||
|  |         { | ||
|  |             functions_.destroy(tmp_functions_); | ||
|  |         } | ||
|  | 
 | ||
|  |         void commit() | ||
|  |         { | ||
|  |             functions_.current_ = tmp_functions_; | ||
|  |             tmp_functions_ = !tmp_functions_; | ||
|  |         } | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <class H, class P> | ||
|  |     class set_hash_functions<H, P, true> | ||
|  |     { | ||
|  |         set_hash_functions(set_hash_functions const&); | ||
|  |         set_hash_functions& operator=(set_hash_functions const&); | ||
|  | 
 | ||
|  |         typedef functions<H, P> 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 | ||
|  | 
 | ||
|  | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | ||
|  | #   define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T) | ||
|  | #else | ||
|  |     struct please_ignore_this_overload { | ||
|  |         typedef please_ignore_this_overload type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <typename T> | ||
|  |     struct rv_ref_impl { | ||
|  |         typedef BOOST_RV_REF(T) type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <typename T> | ||
|  |     struct rv_ref : | ||
|  |         boost::detail::if_true< | ||
|  |             boost::is_class<T>::value | ||
|  |         >::BOOST_NESTED_TEMPLATE then < | ||
|  |             boost::unordered::detail::rv_ref_impl<T>, | ||
|  |             please_ignore_this_overload | ||
|  |         >::type | ||
|  |     {}; | ||
|  | 
 | ||
|  | #   define BOOST_UNORDERED_RV_REF(T) \ | ||
|  |         typename boost::unordered::detail::rv_ref<T>::type | ||
|  | #endif | ||
|  | }}} | ||
|  | 
 | ||
|  | #endif |