| 
									
										
										
										
											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
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <boost/unordered/detail/node.hpp>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | namespace boost { namespace unordered { namespace detail { | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  |      | 
					
						
							|  |  |  |     ////////////////////////////////////////////////////////////////////////////
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     //
 | 
					
						
							|  |  |  |     // Now the main data structure:
 | 
					
						
							|  |  |  |     //
 | 
					
						
							| 
									
										
										
										
											2011-04-17 00:31:35 +00:00
										 |  |  |     // buckets<A, Unique>           functions<H, P>
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     //       |                              |
 | 
					
						
							|  |  |  |     //       +---------------+--------------+
 | 
					
						
							|  |  |  |     //                       |
 | 
					
						
							|  |  |  |     //                   table<T>
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // T is a class which contains typedefs for all the types we need.
 | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     // buckets
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // This is responsible for allocating and deallocating buckets and nodes.
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // Notes:
 | 
					
						
							|  |  |  |     // 1. For the sake exception safety the consturctors don't allocate
 | 
					
						
							|  |  |  |     //    anything.
 | 
					
						
							|  |  |  |     // 2. It's the callers responsibility to allocate the buckets before calling
 | 
					
						
							|  |  |  |     //    any of the methods (other than getters and setters).
 | 
					
						
							| 
									
										
										
										
											2009-10-25 10:55:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     template <class A, bool Unique> | 
					
						
							|  |  |  |     class buckets | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         buckets(buckets const&); | 
					
						
							|  |  |  |         buckets& operator=(buckets const&); | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  |         // Types
 | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         typedef BOOST_DEDUCED_TYPENAME ::boost::detail::if_true<Unique>:: | 
					
						
							|  |  |  |             BOOST_NESTED_TEMPLATE then< | 
					
						
							|  |  |  |                 ::boost::unordered::detail::ungrouped_node<A>, | 
					
						
							|  |  |  |                 ::boost::unordered::detail::grouped_node<A> | 
					
						
							|  |  |  |             >::type node; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         typedef A value_allocator; | 
					
						
							|  |  |  |         typedef ::boost::unordered::detail::bucket<A> bucket; | 
					
						
							| 
									
										
										
										
											2011-08-11 21:17:57 +00:00
										 |  |  |         typedef BOOST_DEDUCED_TYPENAME allocator_traits<A>::value_type value_type; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         typedef BOOST_DEDUCED_TYPENAME bucket::bucket_allocator | 
					
						
							|  |  |  |             bucket_allocator; | 
					
						
							| 
									
										
										
										
											2011-08-11 21:17:57 +00:00
										 |  |  |         typedef BOOST_DEDUCED_TYPENAME allocator_traits<bucket_allocator>::pointer bucket_ptr; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         typedef BOOST_DEDUCED_TYPENAME rebind_wrap<value_allocator, node>::type | 
					
						
							|  |  |  |             node_allocator; | 
					
						
							| 
									
										
										
										
											2011-08-11 21:17:57 +00:00
										 |  |  |         typedef BOOST_DEDUCED_TYPENAME allocator_traits<node_allocator>::pointer real_node_ptr; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Members
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bucket_ptr buckets_; | 
					
						
							|  |  |  |         std::size_t bucket_count_; | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |         std::size_t size_; | 
					
						
							| 
									
										
										
										
											2011-08-15 21:34:01 +00:00
										 |  |  |         compressed_pair<bucket_allocator, node_allocator> allocators_; | 
					
						
							| 
									
										
										
										
											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.
 | 
					
						
							| 
									
										
										
										
											2011-08-11 21:17:57 +00:00
										 |  |  |             return prev_prime(allocator_traits<bucket_allocator>::max_size(bucket_alloc()) - 1); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |         // Constructors and Destructors
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         buckets(node_allocator const& a, std::size_t bucket_count) | 
					
						
							|  |  |  |           : buckets_(), | 
					
						
							|  |  |  |             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-08-15 21:34:01 +00:00
										 |  |  |         buckets(buckets& b, move_tag m) | 
					
						
							| 
									
										
										
										
											2011-08-11 21:18:19 +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); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         template <typename T> | 
					
						
							| 
									
										
										
										
											2011-08-15 21:34:01 +00:00
										 |  |  |         buckets(table<T>& x, move_tag m) | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:29 +00:00
										 |  |  |           : buckets_(), | 
					
						
							|  |  |  |             bucket_count_(x.bucket_count_), | 
					
						
							| 
									
										
										
										
											2011-08-15 21:34:01 +00:00
										 |  |  |             allocators_(x.allocators_, m) | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:29 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             swap(x); | 
					
						
							|  |  |  |             x.size_ = 0; | 
					
						
							| 
									
										
										
										
											2011-08-11 21:18:19 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         inline ~buckets() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if(this->buckets_) { this->delete_buckets(); } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         void create_buckets() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // The array constructor will clean up in the event of an
 | 
					
						
							|  |  |  |             // exception.
 | 
					
						
							|  |  |  |             allocator_array_constructor<bucket_allocator> | 
					
						
							|  |  |  |                 constructor(bucket_alloc()); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             // Creates an extra bucket to act as the start node.
 | 
					
						
							|  |  |  |             constructor.construct(bucket(), this->bucket_count_ + 1); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             // Only release the buckets once everything is successfully
 | 
					
						
							|  |  |  |             // done.
 | 
					
						
							|  |  |  |             this->buckets_ = constructor.release(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											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()); | 
					
						
							|  |  |  |             std::swap(buckets_, other.buckets_); | 
					
						
							|  |  |  |             std::swap(bucket_count_, other.bucket_count_); | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |             std::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_); | 
					
						
							|  |  |  |             std::swap(buckets_, other.buckets_); | 
					
						
							|  |  |  |             std::swap(bucket_count_, other.bucket_count_); | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |             std::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-04-16 18:47:33 +00:00
										 |  |  |             other.buckets_ = bucket_ptr(); | 
					
						
							|  |  |  |             other.bucket_count_ = 0; | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |             other.size_ = 0; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         std::size_t bucket_size(std::size_t index) const | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |             if (!this->size_) return 0; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             node_ptr ptr = this->buckets_[index].next_; | 
					
						
							|  |  |  |             if (!ptr) return 0; | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  |             ptr = ptr->next_; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |      | 
					
						
							|  |  |  |             std::size_t count = 0; | 
					
						
							|  |  |  |             while(BOOST_UNORDERED_BORLAND_BOOL(ptr) && | 
					
						
							|  |  |  |                 node::get_hash(ptr) % this->bucket_count_ == index) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ++count; | 
					
						
							|  |  |  |                 ptr = ptr->next_; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             return count; | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         node_ptr bucket_begin(std::size_t bucket_index) const | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |             if (!this->size_) return node_ptr(); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             bucket& b = this->buckets_[bucket_index]; | 
					
						
							|  |  |  |             if (!b.next_) return node_ptr(); | 
					
						
							|  |  |  |             return b.next_->next_; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         // For the remaining functions, buckets_ must not be null.
 | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         bucket_ptr get_bucket(std::size_t bucket_index) const | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return buckets_ + static_cast<std::ptrdiff_t>(bucket_index); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |         float load_factor() const | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             BOOST_ASSERT(this->bucket_count_ != 0); | 
					
						
							|  |  |  |             return static_cast<float>(this->size_) | 
					
						
							|  |  |  |                 / static_cast<float>(this->bucket_count_); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         ////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |         // Delete
 | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         void delete_node(node_ptr n) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2011-08-12 06:26:25 +00:00
										 |  |  |             node* raw_ptr = static_cast<node*>(boost::addressof(*n)); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             real_node_ptr real_ptr(node_alloc().address(*raw_ptr)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ::boost::unordered::detail::destroy(raw_ptr->value_ptr()); | 
					
						
							| 
									
										
										
										
											2011-08-11 21:18:43 +00:00
										 |  |  |             allocator_traits<node_allocator>::destroy(node_alloc(), raw_ptr); | 
					
						
							| 
									
										
										
										
											2011-08-11 21:17:57 +00:00
										 |  |  |             allocator_traits<node_allocator>::deallocate(node_alloc(), real_ptr, 1); | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             --this->size_; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         void delete_buckets() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             bucket_ptr end = this->get_bucket(this->bucket_count_); | 
					
						
							|  |  |  |             node_ptr n = (end)->next_; | 
					
						
							|  |  |  |             while(BOOST_UNORDERED_BORLAND_BOOL(n)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 node_ptr node_to_delete = n; | 
					
						
							|  |  |  |                 n = n->next_; | 
					
						
							|  |  |  |                 delete_node(node_to_delete); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             ++end; | 
					
						
							|  |  |  |             for(bucket_ptr begin = this->buckets_; begin != end; ++begin) { | 
					
						
							| 
									
										
										
										
											2011-08-12 06:26:25 +00:00
										 |  |  |                 allocator_traits<bucket_allocator>::destroy(bucket_alloc(), | 
					
						
							| 
									
										
										
										
											2011-08-18 19:28:41 +00:00
										 |  |  |                     boost::addressof(*begin)); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2011-08-11 21:17:57 +00:00
										 |  |  |             allocator_traits<bucket_allocator>::deallocate(bucket_alloc(), this->buckets_, this->bucket_count_ + 1); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |      | 
					
						
							|  |  |  |             this->buckets_ = bucket_ptr(); | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |             BOOST_ASSERT(this->size_ == 0); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         std::size_t delete_nodes(node_ptr begin, node_ptr end) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             std::size_t count = 0; | 
					
						
							|  |  |  |             while(begin != end) { | 
					
						
							|  |  |  |                 node_ptr n = begin; | 
					
						
							|  |  |  |                 begin = begin->next_; | 
					
						
							|  |  |  |                 delete_node(n); | 
					
						
							|  |  |  |                 ++count; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return count; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |         void clear() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if(!this->size_) return; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             bucket_ptr end = this->get_bucket(this->bucket_count_); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             node_ptr n = (end)->next_; | 
					
						
							|  |  |  |             while(BOOST_UNORDERED_BORLAND_BOOL(n)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 node_ptr node_to_delete = n; | 
					
						
							|  |  |  |                 n = n->next_; | 
					
						
							|  |  |  |                 this->delete_node(node_to_delete); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             ++end; | 
					
						
							|  |  |  |             for(bucket_ptr begin = this->buckets_; begin != end; ++begin) { | 
					
						
							|  |  |  |                 begin->next_ = bucket_ptr(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             this->size_ = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         node_ptr erase(node_ptr r) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             BOOST_ASSERT(r); | 
					
						
							|  |  |  |             node_ptr next = r->next_; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             bucket_ptr bucket = this->get_bucket( | 
					
						
							|  |  |  |                 node::get_hash(r) % this->bucket_count_); | 
					
						
							|  |  |  |             node_ptr prev = node::unlink_node(*bucket, r); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             this->fix_buckets(bucket, prev, next); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             this->delete_node(r); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             return next; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         node_ptr erase_range(node_ptr r1, node_ptr r2) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if (r1 == r2) return r2; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             std::size_t bucket_index = node::get_hash(r1) % this->bucket_count_; | 
					
						
							|  |  |  |             node_ptr prev = node::unlink_nodes( | 
					
						
							|  |  |  |                 this->buckets_[bucket_index], r1, r2); | 
					
						
							|  |  |  |             this->fix_buckets_range(bucket_index, prev, r1, r2); | 
					
						
							|  |  |  |             this->delete_nodes(r1, r2); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             return r2; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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.
 | 
					
						
							|  |  |  |         void fix_buckets(bucket_ptr bucket, node_ptr prev, node_ptr next) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if (!next) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 if (bucket->next_ == prev) bucket->next_ = node_ptr(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 bucket_ptr next_bucket = this->get_bucket( | 
					
						
							|  |  |  |                     node::get_hash(next) % this->bucket_count_); | 
					
						
							|  |  |  |                 if (next_bucket != bucket) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     next_bucket->next_ = prev; | 
					
						
							|  |  |  |                     if (bucket->next_ == prev) bucket->next_ = node_ptr(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											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.
 | 
					
						
							|  |  |  |         void fix_buckets_range( | 
					
						
							|  |  |  |             std::size_t bucket_index, node_ptr prev, node_ptr begin, node_ptr end) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             node_ptr n = begin; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             // 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(;;) { | 
					
						
							|  |  |  |                     n = n->next_; | 
					
						
							|  |  |  |                     if (n == end) return; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |                     std::size_t new_bucket_index = | 
					
						
							|  |  |  |                         node::get_hash(n) % this->bucket_count_; | 
					
						
							|  |  |  |                     if (bucket_index != new_bucket_index) { | 
					
						
							|  |  |  |                         bucket_index = new_bucket_index; | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             // Iterate through the remaining nodes, clearing out the bucket
 | 
					
						
							|  |  |  |             // pointers.
 | 
					
						
							|  |  |  |             this->buckets_[bucket_index].next_ = bucket_ptr(); | 
					
						
							|  |  |  |             for(;;) { | 
					
						
							|  |  |  |                 n = n->next_; | 
					
						
							|  |  |  |                 if (n == end) break; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |                 std::size_t new_bucket_index = | 
					
						
							|  |  |  |                     node::get_hash(n) % this->bucket_count_; | 
					
						
							|  |  |  |                 if (bucket_index != new_bucket_index) { | 
					
						
							|  |  |  |                     bucket_index = new_bucket_index; | 
					
						
							|  |  |  |                     this->buckets_[bucket_index].next_ = bucket_ptr(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             // Finally fix the bucket containing the trailing node.
 | 
					
						
							|  |  |  |             if (BOOST_UNORDERED_BORLAND_BOOL(n)) { | 
					
						
							|  |  |  |                 this->buckets_[node::get_hash(n) % this->bucket_count_].next_ | 
					
						
							|  |  |  |                     = prev; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Iterate through the nodes placing them in the correct buckets.
 | 
					
						
							|  |  |  |         // pre: prev->next_ is not null.
 | 
					
						
							|  |  |  |         node_ptr place_in_bucket(node_ptr prev, node_ptr end) { | 
					
						
							|  |  |  |             bucket_ptr b = this->get_bucket(node::get_hash(prev->next_) % this->bucket_count_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!b->next_) { | 
					
						
							|  |  |  |                 b->next_ = prev; | 
					
						
							|  |  |  |                 return end; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 node_ptr next = end->next_; | 
					
						
							|  |  |  |                 end->next_ = b->next_->next_; | 
					
						
							|  |  |  |                 b->next_->next_ = prev->next_; | 
					
						
							|  |  |  |                 prev->next_ = next; | 
					
						
							|  |  |  |                 return prev; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         void copy_buckets_to(buckets&) const; | 
					
						
							| 
									
										
										
										
											2011-08-03 08:34:33 +00:00
										 |  |  |         void move_buckets_to(buckets&) const; | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |         void rehash_impl(std::size_t); | 
					
						
							| 
									
										
										
										
											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-04-16 18:47:33 +00:00
										 |  |  |         friend class 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-08-15 21:34:01 +00:00
										 |  |  |         typedef compressed_pair<H, P> function_pair; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         typedef BOOST_DEDUCED_TYPENAME ::boost::aligned_storage< | 
					
						
							|  |  |  |             sizeof(function_pair), | 
					
						
							|  |  |  |             ::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) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             ::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-04-16 18:47:33 +00:00
										 |  |  |             destroy(current_); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         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_; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  |     ////////////////////////////////////////////////////////////////////////////
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     // Node Constructors
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-07 08:55:28 +00:00
										 |  |  | #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     template <class T, class... Args> | 
					
						
							|  |  |  |     inline void construct_impl(T*, void* address, Args&&... args) | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         new(address) T(std::forward<Args>(args)...); | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _)                       \
 | 
					
						
							|  |  |  |     template <                                                                 \ | 
					
						
							|  |  |  |         class T,                                                               \ | 
					
						
							|  |  |  |         BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)                           \ | 
					
						
							|  |  |  |     >                                                                          \ | 
					
						
							|  |  |  |     inline void construct_impl(                                                \ | 
					
						
							|  |  |  |         T*, void* address,                                                     \ | 
					
						
							|  |  |  |         BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)                         \ | 
					
						
							|  |  |  |     )                                                                          \ | 
					
						
							|  |  |  |     {                                                                          \ | 
					
						
							|  |  |  |         new(address) T(                                                        \ | 
					
						
							|  |  |  |             BOOST_UNORDERED_CALL_PARAMS(z, num_params));                       \ | 
					
						
							|  |  |  |     }                                                                          \ | 
					
						
							|  |  |  |                                                                                \ | 
					
						
							|  |  |  |     template <class First, class Second, class Key,                            \ | 
					
						
							|  |  |  |         BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)                           \ | 
					
						
							|  |  |  |     >                                                                          \ | 
					
						
							|  |  |  |     inline void construct_impl(                                                \ | 
					
						
							|  |  |  |         std::pair<First, Second>*, void* address,                              \ | 
					
						
							|  |  |  |         Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params))          \ | 
					
						
							|  |  |  |     {                                                                          \ | 
					
						
							|  |  |  |         new(address) std::pair<First, Second>(k,                               \ | 
					
						
							|  |  |  |             Second(BOOST_UNORDERED_CALL_PARAMS(z, num_params)));               \ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, | 
					
						
							|  |  |  |         BOOST_UNORDERED_CONSTRUCT_IMPL, _) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef BOOST_UNORDERED_CONSTRUCT_IMPL
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ///////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // Node construction
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template <class Alloc, bool Unique> | 
					
						
							|  |  |  |     class node_constructor | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         typedef ::boost::unordered::detail::buckets<Alloc, Unique> buckets; | 
					
						
							|  |  |  |         typedef BOOST_DEDUCED_TYPENAME buckets::node node; | 
					
						
							|  |  |  |         typedef BOOST_DEDUCED_TYPENAME buckets::real_node_ptr real_node_ptr; | 
					
						
							|  |  |  |         typedef BOOST_DEDUCED_TYPENAME buckets::value_type value_type; | 
					
						
							| 
									
										
										
										
											2011-08-11 21:17:57 +00:00
										 |  |  |         typedef BOOST_DEDUCED_TYPENAME buckets::node_allocator node_allocator; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         buckets& buckets_; | 
					
						
							|  |  |  |         real_node_ptr node_; | 
					
						
							|  |  |  |         bool node_constructed_; | 
					
						
							|  |  |  |         bool value_constructed_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         node_constructor(buckets& m) : | 
					
						
							|  |  |  |             buckets_(m), | 
					
						
							|  |  |  |             node_(), | 
					
						
							|  |  |  |             node_constructed_(false), | 
					
						
							|  |  |  |             value_constructed_(false) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ~node_constructor(); | 
					
						
							|  |  |  |         void construct_preamble(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-07 08:55:28 +00:00
										 |  |  | #if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         template <class... Args> | 
					
						
							|  |  |  |         void construct(Args&&... args) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             construct_preamble(); | 
					
						
							|  |  |  |             construct_impl((value_type*) 0, node_->address(), | 
					
						
							|  |  |  |                 std::forward<Args>(args)...); | 
					
						
							|  |  |  |             value_constructed_ = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define BOOST_UNORDERED_CONSTRUCT(z, num_params, _)                            \
 | 
					
						
							|  |  |  |         template <                                                             \ | 
					
						
							|  |  |  |             BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)                       \ | 
					
						
							|  |  |  |         >                                                                      \ | 
					
						
							|  |  |  |         void construct(                                                        \ | 
					
						
							|  |  |  |             BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)                     \ | 
					
						
							|  |  |  |         )                                                                      \ | 
					
						
							|  |  |  |         {                                                                      \ | 
					
						
							|  |  |  |             construct_preamble();                                              \ | 
					
						
							|  |  |  |             construct_impl(                                                    \ | 
					
						
							|  |  |  |                 (value_type*) 0, node_->address(),                             \ | 
					
						
							|  |  |  |                 BOOST_UNORDERED_CALL_PARAMS(z, num_params)                     \ | 
					
						
							|  |  |  |             );                                                                 \ | 
					
						
							|  |  |  |             value_constructed_ = true;                                         \ | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, | 
					
						
							|  |  |  |             BOOST_UNORDERED_CONSTRUCT, _) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef BOOST_UNORDERED_CONSTRUCT
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         template <class K, class M> | 
					
						
							|  |  |  |         void construct_pair(K const& k, M*) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             construct_preamble(); | 
					
						
							|  |  |  |             new(node_->address()) value_type(k, M());                     | 
					
						
							|  |  |  |             value_constructed_ = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         value_type& value() const | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             BOOST_ASSERT(node_); | 
					
						
							|  |  |  |             return node_->value(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // no throw
 | 
					
						
							|  |  |  |         BOOST_DEDUCED_TYPENAME buckets::node_ptr release() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             real_node_ptr p = node_; | 
					
						
							|  |  |  |             node_ = real_node_ptr(); | 
					
						
							|  |  |  |             // node_ptr cast
 | 
					
						
							|  |  |  |             return buckets_.bucket_alloc().address(*p); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  |         node_constructor(node_constructor const&); | 
					
						
							|  |  |  |         node_constructor& operator=(node_constructor const&); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     // node_constructor
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template <class Alloc, bool Unique> | 
					
						
							|  |  |  |     inline node_constructor<Alloc, Unique>::~node_constructor() | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         if (node_) { | 
					
						
							|  |  |  |             if (value_constructed_) { | 
					
						
							|  |  |  | #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
 | 
					
						
							|  |  |  |                 struct dummy { node<Alloc, Grouped> x; }; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |                 ::boost::unordered::detail::destroy(node_->value_ptr()); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (node_constructed_) | 
					
						
							| 
									
										
										
										
											2011-08-12 06:26:25 +00:00
										 |  |  |                 allocator_traits<node_allocator>::destroy(buckets_.node_alloc(), | 
					
						
							| 
									
										
										
										
											2011-08-18 19:28:41 +00:00
										 |  |  |                     boost::addressof(*node_)); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-11 21:17:57 +00:00
										 |  |  |             allocator_traits<node_allocator>::deallocate(buckets_.node_alloc(), node_, 1); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template <class Alloc, bool Unique> | 
					
						
							|  |  |  |     inline void node_constructor<Alloc, Unique>::construct_preamble() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if(!node_) { | 
					
						
							|  |  |  |             node_constructed_ = false; | 
					
						
							|  |  |  |             value_constructed_ = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-11 21:17:57 +00:00
										 |  |  |             node_ = allocator_traits<node_allocator>::allocate(buckets_.node_alloc(), 1); | 
					
						
							| 
									
										
										
										
											2011-08-12 06:26:25 +00:00
										 |  |  |             allocator_traits<node_allocator>::construct(buckets_.node_alloc(), | 
					
						
							| 
									
										
										
										
											2011-08-18 19:28:41 +00:00
										 |  |  |                 boost::addressof(*node_), node()); | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             node_->init(buckets_.bucket_alloc().address(*node_)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             node_constructed_ = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             BOOST_ASSERT(node_constructed_ && value_constructed_); | 
					
						
							|  |  |  |             ::boost::unordered::detail::destroy(node_->value_ptr()); | 
					
						
							|  |  |  |             value_constructed_ = false; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ////////////////////////////////////////////////////////////////////////////
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     // copy_buckets_to
 | 
					
						
							|  |  |  |     //
 | 
					
						
							| 
									
										
										
										
											2011-08-03 08:34:33 +00:00
										 |  |  |     // basic exception safety. If an exception is thrown this will
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     // leave dst partially filled and the buckets unset.
 | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |     template <class A, bool Unique> | 
					
						
							|  |  |  |     void buckets<A, Unique>::copy_buckets_to(buckets& dst) const | 
					
						
							| 
									
										
										
										
											2009-09-20 21:55:15 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |         BOOST_ASSERT(!dst.buckets_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dst.create_buckets(); | 
					
						
							|  |  |  |         bucket_ptr dst_start = dst.get_bucket(dst.bucket_count_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         {         | 
					
						
							|  |  |  |             node_constructor<A, Unique> a(dst); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             node_ptr n = this->buckets_[this->bucket_count_].next_; | 
					
						
							|  |  |  |             node_ptr prev = dst_start; | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |             while(n) { | 
					
						
							|  |  |  |                 std::size_t hash = node::get_hash(n); | 
					
						
							|  |  |  |                 node_ptr group_end = node::next_group(n); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |                 a.construct(node::get_value(n)); | 
					
						
							|  |  |  |                 node_ptr first_node = a.release(); | 
					
						
							|  |  |  |                 node::set_hash(first_node, hash); | 
					
						
							|  |  |  |                 node_ptr end = prev->next_ = first_node; | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |                 ++dst.size_; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |      | 
					
						
							|  |  |  |                 for(n = n->next_; n != group_end; n = n->next_) { | 
					
						
							|  |  |  |                     a.construct(node::get_value(n)); | 
					
						
							|  |  |  |                     end = a.release(); | 
					
						
							|  |  |  |                     node::set_hash(end, hash); | 
					
						
							|  |  |  |                     node::add_after_node(end, first_node); | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |                     ++dst.size_; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |                 } | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |                 prev = dst.place_in_bucket(prev, end); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-08-03 08:34:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |     // move_buckets_to
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // Basic exception safety. The source nodes are left in an unusable state
 | 
					
						
							|  |  |  |     // if an exception throws.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template <class A, bool Unique> | 
					
						
							|  |  |  |     void buckets<A, Unique>::move_buckets_to(buckets& dst) const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         BOOST_ASSERT(!dst.buckets_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dst.create_buckets(); | 
					
						
							|  |  |  |         bucket_ptr dst_start = dst.get_bucket(dst.bucket_count_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         {         | 
					
						
							|  |  |  |             node_constructor<A, Unique> a(dst); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |             node_ptr n = this->buckets_[this->bucket_count_].next_; | 
					
						
							|  |  |  |             node_ptr prev = dst_start; | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |             while(n) { | 
					
						
							|  |  |  |                 std::size_t hash = node::get_hash(n); | 
					
						
							|  |  |  |                 node_ptr group_end = node::next_group(n); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |                 a.construct(boost::move(node::get_value(n))); | 
					
						
							|  |  |  |                 node_ptr first_node = a.release(); | 
					
						
							|  |  |  |                 node::set_hash(first_node, hash); | 
					
						
							|  |  |  |                 node_ptr end = prev->next_ = first_node; | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:29 +00:00
										 |  |  |                 ++dst.size_; | 
					
						
							| 
									
										
										
										
											2011-08-03 08:34:33 +00:00
										 |  |  |      | 
					
						
							|  |  |  |                 for(n = n->next_; n != group_end; n = n->next_) { | 
					
						
							|  |  |  |                     a.construct(boost::move(node::get_value(n))); | 
					
						
							|  |  |  |                     end = a.release(); | 
					
						
							|  |  |  |                     node::set_hash(end, hash); | 
					
						
							|  |  |  |                     node::add_after_node(end, first_node); | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  |                     ++dst.size_; | 
					
						
							| 
									
										
										
										
											2011-08-03 08:34:33 +00:00
										 |  |  |                 } | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |                 prev = dst.place_in_bucket(prev, end); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // strong otherwise exception safety
 | 
					
						
							|  |  |  |     template <class A, bool Unique> | 
					
						
							|  |  |  |     void buckets<A, Unique>::rehash_impl(std::size_t num_buckets) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         BOOST_ASSERT(this->size_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         buckets dst(this->node_alloc(), num_buckets); | 
					
						
							|  |  |  |         dst.create_buckets(); | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         bucket_ptr src_start = this->get_bucket(this->bucket_count_); | 
					
						
							|  |  |  |         bucket_ptr dst_start = dst.get_bucket(dst.bucket_count_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dst_start->next_ = src_start->next_; | 
					
						
							|  |  |  |         src_start->next_ = bucket_ptr(); | 
					
						
							|  |  |  |         dst.size_ = this->size_; | 
					
						
							|  |  |  |         this->size_ = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         node_ptr prev = dst_start; | 
					
						
							|  |  |  |         while (BOOST_UNORDERED_BORLAND_BOOL(prev->next_)) | 
					
						
							|  |  |  |             prev = dst.place_in_bucket(prev, node::next_group2(prev)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Swap the new nodes back into the container and setup the
 | 
					
						
							|  |  |  |         // variables.
 | 
					
						
							|  |  |  |         dst.swap(*this); // no throw
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  | }}} | 
					
						
							| 
									
										
										
										
											2009-09-04 07:03:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #endif
 |