// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard. // Copyright (C) 2005-2009 Daniel James // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED #define BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED #include #include #include #include namespace boost { namespace unordered_detail { //////////////////////////////////////////////////////////////////////////// // Buckets template inline std::size_t hash_buckets::max_bucket_count() const { // -1 to account for the sentinel. return prev_prime(this->bucket_alloc().max_size() - 1); } template inline BOOST_DEDUCED_TYPENAME hash_buckets::bucket_ptr hash_buckets::get_bucket(std::size_t num) const { return buckets_ + static_cast(num); } template inline BOOST_DEDUCED_TYPENAME hash_buckets::bucket_ptr hash_buckets::bucket_ptr_from_hash(std::size_t hashed) const { return get_bucket(hashed % bucket_count_); } template std::size_t hash_buckets::bucket_size(std::size_t index) const { if(!buckets_) return 0; bucket_ptr ptr = get_bucket(index)->next_; std::size_t count = 0; while(ptr) { ++count; ptr = ptr->next_; } return count; } template inline BOOST_DEDUCED_TYPENAME hash_buckets::node_ptr hash_buckets::bucket_begin(std::size_t num) const { return buckets_ ? get_bucket(num)->next_ : node_ptr(); } //////////////////////////////////////////////////////////////////////////// // Delete template inline void hash_buckets::delete_node(node_ptr b) { node* raw_ptr = static_cast(&*b); boost::unordered_detail::destroy(&raw_ptr->value()); real_node_ptr n(node_alloc().address(*raw_ptr)); node_alloc().destroy(n); node_alloc().deallocate(n, 1); } template inline void hash_buckets::clear_bucket(bucket_ptr b) { node_ptr node_it = b->next_; b->next_ = node_ptr(); while(node_it) { node_ptr node_to_delete = node_it; node_it = node_it->next_; delete_node(node_to_delete); } } template inline void hash_buckets::delete_buckets() { bucket_ptr end = this->get_bucket(this->bucket_count_); for(bucket_ptr begin = this->buckets_; begin != end; ++begin) { clear_bucket(begin); } // Destroy the buckets (including the sentinel bucket). ++end; for(bucket_ptr begin = this->buckets_; begin != end; ++begin) { bucket_alloc().destroy(begin); } bucket_alloc().deallocate(this->buckets_, this->bucket_count_ + 1); this->buckets_ = bucket_ptr(); } template inline std::size_t hash_buckets::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; } //////////////////////////////////////////////////////////////////////////// // Constructors and Destructors template inline hash_buckets::hash_buckets( node_allocator const& a, std::size_t bucket_count) : buckets_(), bucket_count_(bucket_count), allocators_(a,a) { } template inline hash_buckets::~hash_buckets() { if(this->buckets_) { this->delete_buckets(); } } template inline void hash_buckets::create_buckets() { // The array constructor will clean up in the event of an // exception. allocator_array_constructor constructor(bucket_alloc()); // Creates an extra bucket to act as a sentinel. constructor.construct(bucket(), this->bucket_count_ + 1); // Set up the sentinel (node_ptr cast) bucket_ptr sentinel = constructor.get() + static_cast(this->bucket_count_); sentinel->next_ = sentinel; // Only release the buckets once everything is successfully // done. this->buckets_ = constructor.release(); } //////////////////////////////////////////////////////////////////////////// // Constructors and Destructors // no throw template inline void hash_buckets::move(hash_buckets& other) { BOOST_ASSERT(node_alloc() == other.node_alloc()); if(this->buckets_) { this->delete_buckets(); } this->buckets_ = other.buckets_; this->bucket_count_ = other.bucket_count_; other.buckets_ = bucket_ptr(); other.bucket_count_ = 0; } template inline void hash_buckets::swap(hash_buckets& other) { BOOST_ASSERT(node_alloc() == other.node_alloc()); std::swap(buckets_, other.buckets_); std::swap(bucket_count_, other.bucket_count_); } }} #endif