forked from boostorg/unordered
		
	
		
			
				
	
	
		
			184 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
 | 
						|
// 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 <boost/config.hpp>
 | 
						|
#include <boost/assert.hpp>
 | 
						|
#include <boost/unordered/detail/node.hpp>
 | 
						|
#include <boost/unordered/detail/util.hpp>
 | 
						|
 | 
						|
namespace boost { namespace unordered_detail {
 | 
						|
    
 | 
						|
    ////////////////////////////////////////////////////////////////////////////
 | 
						|
    // Buckets
 | 
						|
    
 | 
						|
    template <class A, class G>
 | 
						|
    inline std::size_t hash_buckets<A, G>::max_bucket_count() const {
 | 
						|
        // -1 to account for the sentinel.
 | 
						|
        return prev_prime(this->bucket_alloc().max_size() - 1);
 | 
						|
    }
 | 
						|
 | 
						|
    template <class A, class G>
 | 
						|
    inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
 | 
						|
        hash_buckets<A, G>::get_bucket(std::size_t num) const
 | 
						|
    {
 | 
						|
        return buckets_ + static_cast<std::ptrdiff_t>(num);
 | 
						|
    }
 | 
						|
 | 
						|
    template <class A, class G>
 | 
						|
    inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
 | 
						|
        hash_buckets<A, G>::bucket_ptr_from_hash(std::size_t hashed) const
 | 
						|
    {
 | 
						|
        return get_bucket(hashed % bucket_count_);
 | 
						|
    }
 | 
						|
    
 | 
						|
    template <class A, class G>
 | 
						|
    std::size_t hash_buckets<A, G>::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 <class A, class G>
 | 
						|
    inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::node_ptr
 | 
						|
        hash_buckets<A, G>::bucket_begin(std::size_t num) const
 | 
						|
    {
 | 
						|
        return buckets_ ? get_bucket(num)->next_ : node_ptr();
 | 
						|
    }
 | 
						|
 | 
						|
    ////////////////////////////////////////////////////////////////////////////
 | 
						|
    // Delete
 | 
						|
 | 
						|
    template <class A, class G>
 | 
						|
    inline void hash_buckets<A, G>::delete_node(node_ptr b)
 | 
						|
    {
 | 
						|
        node* raw_ptr = static_cast<node*>(&*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 <class A, class G>
 | 
						|
    inline void hash_buckets<A, G>::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 <class A, class G>
 | 
						|
    inline void hash_buckets<A, G>::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 <class A, class G>
 | 
						|
    inline std::size_t hash_buckets<A, G>::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 <class A, class G>
 | 
						|
    inline hash_buckets<A, G>::hash_buckets(
 | 
						|
        node_allocator const& a, std::size_t bucket_count)
 | 
						|
      : buckets_(),
 | 
						|
        bucket_count_(bucket_count),
 | 
						|
        allocators_(a,a)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    template <class A, class G>
 | 
						|
    inline hash_buckets<A, G>::~hash_buckets()
 | 
						|
    {
 | 
						|
        if(this->buckets_) { this->delete_buckets(); }
 | 
						|
    }
 | 
						|
    
 | 
						|
    template <class A, class G>
 | 
						|
    inline void hash_buckets<A, G>::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 a sentinel.
 | 
						|
        constructor.construct(bucket(), this->bucket_count_ + 1);
 | 
						|
 | 
						|
        // Set up the sentinel (node_ptr cast)
 | 
						|
        bucket_ptr sentinel = constructor.get() +
 | 
						|
            static_cast<std::ptrdiff_t>(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 <class A, class G>
 | 
						|
    inline void hash_buckets<A, G>::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 <class A, class G>
 | 
						|
    inline void hash_buckets<A, G>::swap(hash_buckets<A, G>& other)
 | 
						|
    {
 | 
						|
        BOOST_ASSERT(node_alloc() == other.node_alloc());
 | 
						|
        std::swap(buckets_, other.buckets_);
 | 
						|
        std::swap(bucket_count_, other.bucket_count_);
 | 
						|
    }
 | 
						|
}}
 | 
						|
 | 
						|
#endif
 |