| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
 | 
					
						
							| 
									
										
										
										
											2011-06-04 16:17:07 +00:00
										 |  |  | // Copyright (C) 2005-2011 Daniel James
 | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | // 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
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  | #if defined(_MSC_VER) && (_MSC_VER >= 1020)
 | 
					
						
							|  |  |  | # pragma once
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <boost/unordered/detail/util.hpp>
 | 
					
						
							|  |  |  | #include <boost/unordered/detail/allocator_helpers.hpp>
 | 
					
						
							|  |  |  | #include <boost/unordered/detail/emplace_args.hpp>
 | 
					
						
							|  |  |  | #include <boost/type_traits/aligned_storage.hpp>
 | 
					
						
							|  |  |  | #include <boost/type_traits/alignment_of.hpp>
 | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  | #include <boost/swap.hpp>
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  | #include <boost/assert.hpp>
 | 
					
						
							| 
									
										
										
										
											2012-02-18 15:47:59 +00:00
										 |  |  | #include <boost/limits.hpp>
 | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  | #include <boost/iterator.hpp>
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined(BOOST_MSVC)
 | 
					
						
							|  |  |  | #pragma warning(push)
 | 
					
						
							|  |  |  | #pragma warning(disable:4127) // conditional expression is constant
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | namespace boost { namespace unordered { namespace detail { | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     template <typename Types> struct table; | 
					
						
							|  |  |  |     template <typename NodePointer> struct bucket; | 
					
						
							|  |  |  |     struct ptr_bucket; | 
					
						
							| 
									
										
										
										
											2012-02-18 15:47:59 +00:00
										 |  |  |     template <typename A, typename Bucket, typename Node, typename Policy> | 
					
						
							|  |  |  |     struct buckets; | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  |     template <typename Types> struct table_impl; | 
					
						
							|  |  |  |     template <typename Types> struct grouped_table_impl; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ///////////////////////////////////////////////////////////////////
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     //
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |     // Node construction
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template <typename NodeAlloc> | 
					
						
							|  |  |  |     struct node_constructor | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         typedef NodeAlloc node_allocator; | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |         typedef boost::unordered::detail::allocator_traits<NodeAlloc> | 
					
						
							|  |  |  |             node_allocator_traits; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         typedef typename node_allocator_traits::value_type node; | 
					
						
							|  |  |  |         typedef typename node_allocator_traits::pointer node_pointer; | 
					
						
							|  |  |  |         typedef typename node::value_type value_type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         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_constructor(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         void construct_node(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         template <BOOST_UNORDERED_EMPLACE_TEMPLATE> | 
					
						
							|  |  |  |         void construct_value(BOOST_UNORDERED_EMPLACE_ARGS) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_); | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |             boost::unordered::detail::construct_impl( | 
					
						
							|  |  |  |                 node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             value_constructed_ = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         template <typename A0> | 
					
						
							|  |  |  |         void construct_value2(BOOST_FWD_REF(A0) a0) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_); | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |             boost::unordered::detail::construct_impl2( | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |                 node_->value_ptr(), boost::forward<A0>(a0)); | 
					
						
							|  |  |  |             value_constructed_ = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         value_type const& value() const { | 
					
						
							|  |  |  |             BOOST_ASSERT(node_ && node_constructed_ && value_constructed_); | 
					
						
							|  |  |  |             return node_->value(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // no throw
 | 
					
						
							|  |  |  |         node_pointer release() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             node_pointer p = node_; | 
					
						
							|  |  |  |             node_ = node_pointer(); | 
					
						
							|  |  |  |             return p; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  |         node_constructor(node_constructor const&); | 
					
						
							|  |  |  |         node_constructor& operator=(node_constructor const&); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |     template <typename Alloc> | 
					
						
							|  |  |  |     node_constructor<Alloc>::~node_constructor() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (node_) { | 
					
						
							|  |  |  |             if (value_constructed_) { | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |                 boost::unordered::detail::destroy(node_->value_ptr()); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (node_constructed_) { | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |                 node_allocator_traits::destroy(alloc_, | 
					
						
							|  |  |  |                     boost::addressof(*node_)); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             node_allocator_traits::deallocate(alloc_, node_, 1); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template <typename Alloc> | 
					
						
							|  |  |  |     void node_constructor<Alloc>::construct_node() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if(!node_) { | 
					
						
							|  |  |  |             node_constructed_ = false; | 
					
						
							|  |  |  |             value_constructed_ = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             node_ = node_allocator_traits::allocate(alloc_, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |             node_allocator_traits::construct(alloc_, | 
					
						
							|  |  |  |                 boost::addressof(*node_), node()); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             node_->init(static_cast<typename node::link_pointer>(node_)); | 
					
						
							|  |  |  |             node_constructed_ = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             BOOST_ASSERT(node_constructed_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (value_constructed_) | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |                 boost::unordered::detail::destroy(node_->value_ptr()); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |                 value_constructed_ = false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ///////////////////////////////////////////////////////////////////
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     //
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |     // Bucket
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template <typename NodePointer> | 
					
						
							|  |  |  |     struct bucket | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         typedef NodePointer previous_pointer; | 
					
						
							|  |  |  |         previous_pointer next_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bucket() : next_() {} | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         previous_pointer first_from_start() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return next_; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         enum { extra_node = true }; | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |     struct ptr_bucket | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         typedef ptr_bucket* previous_pointer; | 
					
						
							|  |  |  |         previous_pointer next_; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         ptr_bucket() : next_(0) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         previous_pointer first_from_start() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return this; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         enum { extra_node = false }; | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  | }}} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace boost { namespace unordered { namespace iterator_detail { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |     // Iterators
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // all no throw
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template <typename NodePointer, typename Value> struct iterator; | 
					
						
							|  |  |  |     template <typename ConstNodePointer, typename NodePointer, | 
					
						
							|  |  |  |         typename Value> struct c_iterator; | 
					
						
							|  |  |  |     template <typename NodePointer, typename Value, typename Policy> | 
					
						
							|  |  |  |         struct l_iterator; | 
					
						
							|  |  |  |     template <typename ConstNodePointer, typename NodePointer, | 
					
						
							|  |  |  |         typename Value, typename Policy> struct cl_iterator; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Local Iterators
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // all no throw
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template <typename NodePointer, typename Value, typename Policy> | 
					
						
							|  |  |  |     struct l_iterator | 
					
						
							|  |  |  |         : public boost::iterator< | 
					
						
							|  |  |  |             std::forward_iterator_tag, Value, std::ptrdiff_t, | 
					
						
							|  |  |  |             NodePointer, Value&> | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  | #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
 | 
					
						
							|  |  |  |         template <typename ConstNodePointer, typename NodePointer2, | 
					
						
							|  |  |  |                 typename Value2, typename Policy2> | 
					
						
							|  |  |  |         friend struct boost::unordered::iterator_detail::cl_iterator; | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         typedef NodePointer node_pointer; | 
					
						
							|  |  |  |         typedef boost::unordered::iterator_detail::iterator<NodePointer, Value> | 
					
						
							|  |  |  |             iterator; | 
					
						
							|  |  |  |         node_pointer ptr_; | 
					
						
							|  |  |  |         std::size_t bucket_; | 
					
						
							|  |  |  |         std::size_t bucket_count_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         l_iterator() : ptr_() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         l_iterator(iterator x, std::size_t b, std::size_t c) | 
					
						
							|  |  |  |             : ptr_(x.node_), bucket_(b), bucket_count_(c) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Value& operator*() const { | 
					
						
							|  |  |  |             return ptr_->value(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Value* 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 { | 
					
						
							|  |  |  |             return ptr_ == x.ptr_; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bool operator!=(l_iterator x) const { | 
					
						
							|  |  |  |             return ptr_ != x.ptr_; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template <typename ConstNodePointer, typename NodePointer, typename Value, | 
					
						
							|  |  |  |              typename Policy> | 
					
						
							|  |  |  |     struct cl_iterator | 
					
						
							|  |  |  |         : public boost::iterator< | 
					
						
							|  |  |  |             std::forward_iterator_tag, Value, std::ptrdiff_t, | 
					
						
							|  |  |  |             ConstNodePointer, Value const&> | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         friend struct boost::unordered::iterator_detail::l_iterator | 
					
						
							|  |  |  |             <NodePointer, Value, Policy>; | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         typedef NodePointer node_pointer; | 
					
						
							|  |  |  |         typedef boost::unordered::iterator_detail::iterator<NodePointer, Value> | 
					
						
							|  |  |  |             iterator; | 
					
						
							|  |  |  |         node_pointer ptr_; | 
					
						
							|  |  |  |         std::size_t bucket_; | 
					
						
							|  |  |  |         std::size_t bucket_count_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cl_iterator() : ptr_() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cl_iterator(iterator x, std::size_t b, std::size_t c) : | 
					
						
							|  |  |  |             ptr_(x.node_), bucket_(b), bucket_count_(c) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cl_iterator(boost::unordered::iterator_detail::l_iterator< | 
					
						
							|  |  |  |                 NodePointer, Value, Policy> const& x) : | 
					
						
							|  |  |  |             ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_) | 
					
						
							|  |  |  |         {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Value const& | 
					
						
							|  |  |  |             operator*() const { | 
					
						
							|  |  |  |             return ptr_->value(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Value 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) { | 
					
						
							|  |  |  |             return x.ptr_ == y.ptr_; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         friend bool operator!=(cl_iterator const& x, cl_iterator const& y) { | 
					
						
							|  |  |  |             return x.ptr_ != y.ptr_; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template <typename NodePointer, typename Value> | 
					
						
							|  |  |  |     struct iterator | 
					
						
							|  |  |  |         : public boost::iterator< | 
					
						
							|  |  |  |             std::forward_iterator_tag, Value, std::ptrdiff_t, | 
					
						
							|  |  |  |             NodePointer, Value&> | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  | #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
 | 
					
						
							|  |  |  |         template <typename, typename, typename> | 
					
						
							|  |  |  |         friend struct boost::unordered::iterator_detail::c_iterator; | 
					
						
							|  |  |  |         template <typename, typename, typename> | 
					
						
							|  |  |  |         friend struct boost::unordered::iterator_detail::l_iterator; | 
					
						
							|  |  |  |         template <typename, typename, typename, typename> | 
					
						
							|  |  |  |         friend struct boost::unordered::iterator_detail::cl_iterator; | 
					
						
							|  |  |  |         template <typename> | 
					
						
							|  |  |  |         friend struct boost::unordered::detail::table; | 
					
						
							|  |  |  |         template <typename, typename, typename, typename> | 
					
						
							|  |  |  |         friend struct boost::unordered::detail::buckets; | 
					
						
							|  |  |  |         template <typename> | 
					
						
							|  |  |  |         friend struct boost::unordered::detail::table_impl; | 
					
						
							|  |  |  |         template <typename> | 
					
						
							|  |  |  |         friend struct boost::unordered::detail::grouped_table_impl; | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         typedef NodePointer node_pointer; | 
					
						
							|  |  |  |         node_pointer node_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         iterator() : node_() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         explicit iterator(node_pointer const& x) : node_(x) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Value& operator*() const { | 
					
						
							|  |  |  |             return node_->value(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Value* operator->() const { | 
					
						
							|  |  |  |             return &node_->value(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         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 { | 
					
						
							|  |  |  |             return node_ == x.node_; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bool operator!=(iterator const& x) const { | 
					
						
							|  |  |  |             return node_ != x.node_; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template <typename ConstNodePointer, typename NodePointer, typename Value> | 
					
						
							|  |  |  |     struct c_iterator | 
					
						
							|  |  |  |         : public boost::iterator< | 
					
						
							|  |  |  |             std::forward_iterator_tag, Value, std::ptrdiff_t, | 
					
						
							|  |  |  |             ConstNodePointer, Value const&> | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         friend struct boost::unordered::iterator_detail::iterator< | 
					
						
							|  |  |  |                 NodePointer, Value>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
 | 
					
						
							|  |  |  |         template <typename> | 
					
						
							|  |  |  |         friend struct boost::unordered::detail::table; | 
					
						
							|  |  |  |         template <typename, typename, typename, typename> | 
					
						
							|  |  |  |         friend struct boost::unordered::detail::buckets; | 
					
						
							|  |  |  |         template <typename> | 
					
						
							|  |  |  |         friend struct boost::unordered::detail::table_impl; | 
					
						
							|  |  |  |         template <typename> | 
					
						
							|  |  |  |         friend struct boost::unordered::detail::grouped_table_impl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         typedef NodePointer node_pointer; | 
					
						
							|  |  |  |         typedef boost::unordered::iterator_detail::iterator<NodePointer, Value> | 
					
						
							|  |  |  |             iterator; | 
					
						
							|  |  |  |         node_pointer node_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         c_iterator() : node_() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         explicit c_iterator(node_pointer const& x) : node_(x) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         c_iterator(boost::unordered::iterator_detail::iterator< | 
					
						
							|  |  |  |                 NodePointer, Value> const& x) : node_(x.node_) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Value const& operator*() const { | 
					
						
							|  |  |  |             return node_->value(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Value const* operator->() const { | 
					
						
							|  |  |  |             return &node_->value(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         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) { | 
					
						
							|  |  |  |             return x.node_ == y.node_; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         friend bool operator!=(c_iterator const& x, c_iterator const& y) { | 
					
						
							|  |  |  |             return x.node_ != y.node_; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | }}} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace boost { namespace unordered { namespace detail { | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-18 15:47:59 +00:00
										 |  |  |     ///////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // Hash Policy
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // Don't really want buckets to derive from this, but will for now.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     struct pick_policy : | 
					
						
							|  |  |  |         pick_policy_impl< | 
					
						
							|  |  |  |             std::numeric_limits<std::size_t>::digits, | 
					
						
							|  |  |  |             std::numeric_limits<std::size_t>::radix> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |     ///////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // Buckets
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-18 15:47:59 +00:00
										 |  |  |     template <typename A, typename Bucket, typename Node, typename Policy> | 
					
						
							|  |  |  |     struct buckets : Policy | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  |         buckets(buckets const&); | 
					
						
							|  |  |  |         buckets& operator=(buckets const&); | 
					
						
							|  |  |  |     public: | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |         typedef boost::unordered::detail::allocator_traits<A> traits; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         typedef typename traits::value_type value_type; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-08 15:28:26 +00:00
										 |  |  |         typedef Policy policy; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         typedef Node node; | 
					
						
							|  |  |  |         typedef Bucket bucket; | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |         typedef typename boost::unordered::detail::rebind_wrap<A, node>::type | 
					
						
							|  |  |  |             node_allocator; | 
					
						
							|  |  |  |         typedef typename boost::unordered::detail::rebind_wrap<A, bucket>::type | 
					
						
							|  |  |  |             bucket_allocator; | 
					
						
							|  |  |  |         typedef boost::unordered::detail::allocator_traits<node_allocator> | 
					
						
							|  |  |  |             node_allocator_traits; | 
					
						
							|  |  |  |         typedef boost::unordered::detail::allocator_traits<bucket_allocator> | 
					
						
							|  |  |  |             bucket_allocator_traits; | 
					
						
							|  |  |  |         typedef typename node_allocator_traits::pointer | 
					
						
							|  |  |  |             node_pointer; | 
					
						
							|  |  |  |         typedef typename node_allocator_traits::const_pointer | 
					
						
							|  |  |  |             const_node_pointer; | 
					
						
							|  |  |  |         typedef typename bucket_allocator_traits::pointer | 
					
						
							|  |  |  |             bucket_pointer; | 
					
						
							|  |  |  |         typedef typename bucket::previous_pointer | 
					
						
							|  |  |  |             previous_pointer; | 
					
						
							|  |  |  |         typedef boost::unordered::detail::node_constructor<node_allocator> | 
					
						
							|  |  |  |             node_constructor; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  |         typedef boost::unordered::iterator_detail:: | 
					
						
							|  |  |  |             iterator<node_pointer, value_type> iterator; | 
					
						
							|  |  |  |         typedef boost::unordered::iterator_detail:: | 
					
						
							|  |  |  |             c_iterator<const_node_pointer, node_pointer, value_type> c_iterator; | 
					
						
							|  |  |  |         typedef boost::unordered::iterator_detail:: | 
					
						
							|  |  |  |             l_iterator<node_pointer, value_type, policy> l_iterator; | 
					
						
							|  |  |  |         typedef boost::unordered::iterator_detail:: | 
					
						
							|  |  |  |             cl_iterator<const_node_pointer, node_pointer, value_type, policy> | 
					
						
							|  |  |  |             cl_iterator; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         // Members
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         bucket_pointer buckets_; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         std::size_t bucket_count_; | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |         std::size_t size_; | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |         boost::unordered::detail::compressed<bucket_allocator, node_allocator> | 
					
						
							|  |  |  |             allocators_; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         // Data access
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bucket_allocator const& bucket_alloc() const | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return allocators_.first(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         node_allocator const& node_alloc() const | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return allocators_.second(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bucket_allocator& bucket_alloc() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return allocators_.first(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         node_allocator& node_alloc() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return allocators_.second(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         std::size_t max_bucket_count() const | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // -1 to account for the start bucket.
 | 
					
						
							| 
									
										
										
										
											2012-04-08 15:28:26 +00:00
										 |  |  |             return policy::prev_bucket_count( | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |                 bucket_allocator_traits::max_size(bucket_alloc()) - 1); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bucket_pointer get_bucket(std::size_t bucket_index) const | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return buckets_ + static_cast<std::ptrdiff_t>(bucket_index); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         previous_pointer get_previous_start() const | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return this->get_bucket(this->bucket_count_)->first_from_start(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         previous_pointer get_previous_start(std::size_t bucket_index) const | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return this->get_bucket(bucket_index)->next_; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  |         iterator get_start() const | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  |             return iterator(static_cast<node_pointer>( | 
					
						
							|  |  |  |                         this->get_previous_start()->next_)); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  |         iterator get_start(std::size_t bucket_index) const | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             previous_pointer prev = this->get_previous_start(bucket_index); | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  |             return prev ? iterator(static_cast<node_pointer>(prev->next_)) : | 
					
						
							|  |  |  |                 iterator(); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         float load_factor() const | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             BOOST_ASSERT(this->bucket_count_ != 0); | 
					
						
							|  |  |  |             return static_cast<float>(this->size_) | 
					
						
							|  |  |  |                 / static_cast<float>(this->bucket_count_); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         std::size_t bucket_size(std::size_t index) const | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if (!this->size_) return 0; | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  |             iterator it = this->get_start(index); | 
					
						
							|  |  |  |             if (!it.node_) return 0; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             std::size_t count = 0; | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  |             while(it.node_ && policy::to_bucket( | 
					
						
							|  |  |  |                         this->bucket_count_, it.node_->hash_) == index) | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             { | 
					
						
							|  |  |  |                 ++count; | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  |                 ++it; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return count; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ////////////////////////////////////////////////////////////////////////
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         // Constructors
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         buckets(node_allocator const& a, std::size_t bucket_count) : | 
					
						
							|  |  |  |             buckets_(), | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             bucket_count_(bucket_count), | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |             size_(), | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             allocators_(a,a) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-08-11 21:18:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |         buckets(buckets& b, boost::unordered::detail::move_tag m) : | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             buckets_(), | 
					
						
							| 
									
										
										
										
											2011-08-11 21:18:43 +00:00
										 |  |  |             bucket_count_(b.bucket_count_), | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |             size_(), | 
					
						
							| 
									
										
										
										
											2011-08-15 21:34:01 +00:00
										 |  |  |             allocators_(b.allocators_, m) | 
					
						
							| 
									
										
										
										
											2011-08-11 21:18:19 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:29 +00:00
										 |  |  |             swap(b); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         template <typename Types> | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |         buckets(boost::unordered::detail::table<Types>& x, | 
					
						
							|  |  |  |                 boost::unordered::detail::move_tag m) : | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             buckets_(), | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:29 +00:00
										 |  |  |             bucket_count_(x.bucket_count_), | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             size_(), | 
					
						
							| 
									
										
										
										
											2011-08-15 21:34:01 +00:00
										 |  |  |             allocators_(x.allocators_, m) | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:29 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             swap(x); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         ////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |         // Create buckets
 | 
					
						
							|  |  |  |         // (never called in constructor to avoid exception issues)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         void create_buckets() | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |             boost::unordered::detail::array_constructor<bucket_allocator> | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                 constructor(bucket_alloc()); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             // Creates an extra bucket to act as the start node.
 | 
					
						
							|  |  |  |             constructor.construct(bucket(), this->bucket_count_ + 1); | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             if (bucket::extra_node) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 node_constructor a(this->node_alloc()); | 
					
						
							|  |  |  |                 a.construct_node(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |                 (constructor.get() + | 
					
						
							|  |  |  |                     static_cast<std::ptrdiff_t>(this->bucket_count_))->next_ = | 
					
						
							|  |  |  |                         a.release(); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             this->buckets_ = constructor.release(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |         // Swap and Move
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-11 21:18:43 +00:00
										 |  |  |         void swap(buckets& other, false_type = false_type()) | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             BOOST_ASSERT(node_alloc() == other.node_alloc()); | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |             boost::swap(buckets_, other.buckets_); | 
					
						
							|  |  |  |             boost::swap(bucket_count_, other.bucket_count_); | 
					
						
							|  |  |  |             boost::swap(size_, other.size_); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-11 21:18:43 +00:00
										 |  |  |         void swap(buckets& other, true_type) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             allocators_.swap(other.allocators_); | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |             boost::swap(buckets_, other.buckets_); | 
					
						
							|  |  |  |             boost::swap(bucket_count_, other.bucket_count_); | 
					
						
							|  |  |  |             boost::swap(size_, other.size_); | 
					
						
							| 
									
										
										
										
											2011-08-11 21:18:43 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:29 +00:00
										 |  |  |         void move_buckets_from(buckets& other) | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             BOOST_ASSERT(node_alloc() == other.node_alloc()); | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:29 +00:00
										 |  |  |             BOOST_ASSERT(!this->buckets_); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             this->buckets_ = other.buckets_; | 
					
						
							|  |  |  |             this->bucket_count_ = other.bucket_count_; | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |             this->size_ = other.size_; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             other.buckets_ = bucket_pointer(); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             other.bucket_count_ = 0; | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |             other.size_ = 0; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         ////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |         // Delete/destruct
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  |         inline void delete_node(c_iterator n) | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  |             boost::unordered::detail::destroy(n.node_->value_ptr()); | 
					
						
							|  |  |  |             node_allocator_traits::destroy(node_alloc(), | 
					
						
							|  |  |  |                     boost::addressof(*n.node_)); | 
					
						
							|  |  |  |             node_allocator_traits::deallocate(node_alloc(), n.node_, 1); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             --size_; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  |         std::size_t delete_nodes(c_iterator begin, c_iterator end) | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             std::size_t count = 0; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             while(begin != end) { | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  |                 c_iterator n = begin; | 
					
						
							|  |  |  |                 ++begin; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |                 delete_node(n); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                 ++count; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             return count; | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         inline void delete_extra_node(bucket_pointer) {} | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         inline void delete_extra_node(node_pointer n) { | 
					
						
							|  |  |  |             node_allocator_traits::destroy(node_alloc(), boost::addressof(*n)); | 
					
						
							|  |  |  |             node_allocator_traits::deallocate(node_alloc(), n, 1); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         inline ~buckets() | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             this->delete_buckets(); | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         void delete_buckets() | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             if(this->buckets_) { | 
					
						
							|  |  |  |                 previous_pointer prev = this->get_previous_start(); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |                 while(prev->next_) { | 
					
						
							|  |  |  |                     node_pointer n = static_cast<node_pointer>(prev->next_); | 
					
						
							|  |  |  |                     prev->next_ = n->next_; | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  |                     delete_node(iterator(n)); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |                 delete_extra_node(prev); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |                 bucket_pointer end = this->get_bucket(this->bucket_count_ + 1); | 
					
						
							|  |  |  |                 for(bucket_pointer it = this->buckets_; it != end; ++it) | 
					
						
							|  |  |  |                 { | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |                     bucket_allocator_traits::destroy(bucket_alloc(), | 
					
						
							|  |  |  |                         boost::addressof(*it)); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |                 bucket_allocator_traits::deallocate(bucket_alloc(), | 
					
						
							|  |  |  |                     this->buckets_, this->bucket_count_ + 1); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |                 this->buckets_ = bucket_pointer(); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             BOOST_ASSERT(!this->size_); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |         void clear() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if(!this->size_) return; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             previous_pointer prev = this->get_previous_start(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             while(prev->next_) { | 
					
						
							|  |  |  |                 node_pointer n = static_cast<node_pointer>(prev->next_); | 
					
						
							|  |  |  |                 prev->next_ = n->next_; | 
					
						
							| 
									
										
										
										
											2012-04-08 15:30:14 +00:00
										 |  |  |                 delete_node(iterator(n)); | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             bucket_pointer end = this->get_bucket(this->bucket_count_); | 
					
						
							|  |  |  |             for(bucket_pointer it = this->buckets_; it != end; ++it) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 it->next_ = node_pointer(); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             BOOST_ASSERT(!this->size_); | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         // This is called after erasing a node or group of nodes to fix up
 | 
					
						
							|  |  |  |         // the bucket pointers.
 | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |         void fix_buckets(bucket_pointer bucket, | 
					
						
							|  |  |  |                 previous_pointer prev, node_pointer next) | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             if (!next) | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |                 if (bucket->next_ == prev) bucket->next_ = node_pointer(); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |                 bucket_pointer next_bucket = this->get_bucket( | 
					
						
							| 
									
										
										
										
											2012-04-08 15:28:26 +00:00
										 |  |  |                     policy::to_bucket(this->bucket_count_, next->hash_)); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                 if (next_bucket != bucket) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     next_bucket->next_ = prev; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |                     if (bucket->next_ == prev) bucket->next_ = node_pointer(); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         // This is called after erasing a range of nodes to fix any bucket
 | 
					
						
							|  |  |  |         // pointers into that range.
 | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |         void fix_buckets_range(std::size_t bucket_index, | 
					
						
							|  |  |  |                 previous_pointer prev, node_pointer begin, node_pointer end) | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             node_pointer n = begin; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |      | 
					
						
							|  |  |  |             // If we're not at the start of the current bucket, then
 | 
					
						
							|  |  |  |             // go to the start of the next bucket.
 | 
					
						
							|  |  |  |             if (this->get_bucket(bucket_index)->next_ != prev) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 for(;;) { | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |                     n = static_cast<node_pointer>(n->next_); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                     if (n == end) return; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |                     std::size_t new_bucket_index = | 
					
						
							| 
									
										
										
										
											2012-04-08 15:28:26 +00:00
										 |  |  |                         policy::to_bucket(this->bucket_count_, n->hash_); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                     if (bucket_index != new_bucket_index) { | 
					
						
							|  |  |  |                         bucket_index = new_bucket_index; | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             // Iterate through the remaining nodes, clearing out the bucket
 | 
					
						
							|  |  |  |             // pointers.
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             this->get_bucket(bucket_index)->next_ = previous_pointer(); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             for(;;) { | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |                 n = static_cast<node_pointer>(n->next_); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                 if (n == end) break; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |                 std::size_t new_bucket_index = | 
					
						
							| 
									
										
										
										
											2012-04-08 15:28:26 +00:00
										 |  |  |                     policy::to_bucket(this->bucket_count_, n->hash_); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                 if (bucket_index != new_bucket_index) { | 
					
						
							|  |  |  |                     bucket_index = new_bucket_index; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |                     this->get_bucket(bucket_index)->next_ = previous_pointer(); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                 } | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             // Finally fix the bucket containing the trailing node.
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |             if (n) { | 
					
						
							| 
									
										
										
										
											2012-04-08 15:28:26 +00:00
										 |  |  |                 this->get_bucket( | 
					
						
							|  |  |  |                     policy::to_bucket(this->bucket_count_, n->hash_))->next_ | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                     = prev; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |     ////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |     // Functions
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     // 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> class set_hash_functions; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template <class H, class P> | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |     class functions | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-10-07 08:19:53 +00:00
										 |  |  |         friend class boost::unordered::detail::set_hash_functions<H, P>; | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |         functions& operator=(functions const&); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  |         typedef compressed<H, P> function_pair; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |         typedef typename boost::aligned_storage< | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             sizeof(function_pair), | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |             boost::alignment_of<function_pair>::value>::type aligned_function; | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         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_])); | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         void construct(bool which, H const& hf, P const& eq) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             new((void*) &funcs_[which]) function_pair(hf, eq); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         void construct(bool which, function_pair const& f) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             new((void*) &funcs_[which]) function_pair(f); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         void destroy(bool which) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |             boost::unordered::detail::destroy((function_pair*)(&funcs_[which])); | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |          | 
					
						
							|  |  |  |     public: | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |         functions(H const& hf, P const& eq) | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             : current_(false) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             construct(current_, hf, eq); | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |         functions(functions const& bf) | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             : current_(false) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             construct(current_, bf.current()); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |         ~functions() { | 
					
						
							| 
									
										
										
										
											2011-10-06 08:03:25 +00:00
										 |  |  |             this->destroy(current_); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         H const& hash_function() const { | 
					
						
							|  |  |  |             return current().first(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         P const& key_eq() const { | 
					
						
							|  |  |  |             return current().second(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     template <class H, class P> | 
					
						
							|  |  |  |     class set_hash_functions | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         set_hash_functions(set_hash_functions const&); | 
					
						
							|  |  |  |         set_hash_functions& operator=(set_hash_functions const&); | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |         functions<H,P>& functions_; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         bool tmp_functions_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |         set_hash_functions(functions<H,P>& f, H const& h, P const& p) | 
					
						
							|  |  |  |           : functions_(f), | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             tmp_functions_(!f.current_) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             f.construct(tmp_functions_, h, p); | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |         set_hash_functions(functions<H,P>& f, functions<H,P> const& other) | 
					
						
							|  |  |  |           : functions_(f), | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             tmp_functions_(!f.current_) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             f.construct(tmp_functions_, other.current()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ~set_hash_functions() | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |             functions_.destroy(tmp_functions_); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         void commit() | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |             functions_.current_ = tmp_functions_; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             tmp_functions_ = !tmp_functions_; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  | }}} | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:45:14 +00:00
										 |  |  | #if defined(BOOST_MSVC)
 | 
					
						
							|  |  |  | #pragma warning(pop)
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #endif
 |