forked from boostorg/intrusive
206 lines
6.9 KiB
C++
206 lines
6.9 KiB
C++
![]() |
/////////////////////////////////////////////////////////////////////////////
|
|||
|
//
|
|||
|
// (C) Copyright Ion Gazta<74>ga 2007
|
|||
|
//
|
|||
|
// 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)
|
|||
|
//
|
|||
|
// See http://www.boost.org/libs/intrusive for documentation.
|
|||
|
//
|
|||
|
/////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
#ifndef BOOST_INTRUSIVE_HASHTABLE_NODE_HPP
|
|||
|
#define BOOST_INTRUSIVE_HASHTABLE_NODE_HPP
|
|||
|
|
|||
|
#include <boost/intrusive/detail/config_begin.hpp>
|
|||
|
#include <iterator>
|
|||
|
#include <boost/assert.hpp>
|
|||
|
#include <boost/intrusive/detail/pointer_type.hpp>
|
|||
|
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
|||
|
#include <boost/intrusive/circular_list_algorithms.hpp>
|
|||
|
#include <boost/get_pointer.hpp>
|
|||
|
#include <boost/iterator/iterator_facade.hpp>
|
|||
|
#include <boost/utility/enable_if.hpp>
|
|||
|
#include <boost/type_traits/is_convertible.hpp>
|
|||
|
#include <cstddef>
|
|||
|
|
|||
|
namespace boost {
|
|||
|
namespace intrusive {
|
|||
|
namespace detail {
|
|||
|
|
|||
|
template<int Dummy = 0>
|
|||
|
struct prime_list_holder
|
|||
|
{
|
|||
|
static const std::size_t prime_list[];
|
|||
|
static const std::size_t prime_list_size;
|
|||
|
};
|
|||
|
|
|||
|
template<int Dummy>
|
|||
|
const std::size_t prime_list_holder<Dummy>::prime_list[] = {
|
|||
|
53ul, 97ul, 193ul, 389ul, 769ul,
|
|||
|
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
|
|||
|
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
|
|||
|
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
|
|||
|
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
|
|||
|
1610612741ul, 3221225473ul, 4294967291ul };
|
|||
|
|
|||
|
template<int Dummy>
|
|||
|
const std::size_t prime_list_holder<Dummy>::prime_list_size
|
|||
|
= sizeof(prime_list)/sizeof(std::size_t);
|
|||
|
|
|||
|
template <class SlistImpl>
|
|||
|
struct bucket_type_impl
|
|||
|
: public SlistImpl
|
|||
|
{
|
|||
|
bucket_type_impl()
|
|||
|
{}
|
|||
|
|
|||
|
bucket_type_impl(const bucket_type_impl &)
|
|||
|
{}
|
|||
|
|
|||
|
bucket_type_impl &operator=(const bucket_type_impl&)
|
|||
|
{ SlistImpl::clear(); }
|
|||
|
|
|||
|
static typename std::iterator_traits
|
|||
|
<typename SlistImpl::const_iterator>::difference_type
|
|||
|
get_bucket_num
|
|||
|
( typename SlistImpl::const_iterator it
|
|||
|
, const bucket_type_impl<SlistImpl> &first_bucket
|
|||
|
, const bucket_type_impl<SlistImpl> &last_bucket)
|
|||
|
{
|
|||
|
typename SlistImpl::const_iterator
|
|||
|
first(first_bucket.cend()), last(last_bucket.cend());
|
|||
|
|
|||
|
//The end node is embedded in the singly linked list:
|
|||
|
//iterate until we reach it.
|
|||
|
while(!(first.pointed_node() <= it.pointed_node() &&
|
|||
|
it.pointed_node() <= last.pointed_node())){
|
|||
|
++it;
|
|||
|
}
|
|||
|
//Now get the bucket_type_impl from the iterator
|
|||
|
const bucket_type_impl &b = static_cast<const bucket_type_impl&>
|
|||
|
(SlistImpl::container_from_end_iterator(it));
|
|||
|
|
|||
|
//Now just calculate the index b has in the bucket array
|
|||
|
return &b - &first_bucket;
|
|||
|
}
|
|||
|
|
|||
|
static SlistImpl &bucket_to_slist(bucket_type_impl<SlistImpl> &b)
|
|||
|
{ return static_cast<SlistImpl &>(b); }
|
|||
|
|
|||
|
static const SlistImpl &bucket_to_slist(const bucket_type_impl<SlistImpl> &b)
|
|||
|
{ return static_cast<const SlistImpl &>(b); }
|
|||
|
};
|
|||
|
|
|||
|
template<class SlistImpl>
|
|||
|
struct bucket_info_impl
|
|||
|
{
|
|||
|
typedef typename boost::pointer_to_other
|
|||
|
< typename SlistImpl::pointer
|
|||
|
, bucket_type_impl<SlistImpl> >::type bucket_ptr;
|
|||
|
typedef typename SlistImpl::size_type size_type;
|
|||
|
bucket_ptr buckets_;
|
|||
|
size_type buckets_len_;
|
|||
|
};
|
|||
|
|
|||
|
template<class Value, class SlistImpl>
|
|||
|
class hashtable_iterator
|
|||
|
: public boost::iterator_facade
|
|||
|
< hashtable_iterator<Value, SlistImpl>
|
|||
|
, Value
|
|||
|
, boost::forward_traversal_tag
|
|||
|
, Value&
|
|||
|
, typename std::iterator_traits<typename SlistImpl::iterator>::difference_type
|
|||
|
>
|
|||
|
{
|
|||
|
typedef typename SlistImpl::iterator local_iterator;
|
|||
|
typedef typename SlistImpl::const_iterator const_local_iterator;
|
|||
|
typedef typename SlistImpl::value_traits::node_ptr node_ptr;
|
|||
|
typedef typename SlistImpl::value_traits::const_node_ptr const_node_ptr;
|
|||
|
|
|||
|
typedef bucket_type_impl<SlistImpl> bucket_type;
|
|||
|
typedef typename boost::pointer_to_other
|
|||
|
< typename SlistImpl::pointer, bucket_type>::type bucket_ptr;
|
|||
|
typedef typename boost::pointer_to_other
|
|||
|
< typename SlistImpl::pointer, const bucket_type>::type const_bucket_ptr;
|
|||
|
typedef detail::bucket_info_impl<SlistImpl> bucket_info_t;
|
|||
|
typedef typename boost::pointer_to_other
|
|||
|
<bucket_ptr, bucket_info_t>::type bucket_info_ptr;
|
|||
|
typedef typename boost::pointer_to_other
|
|||
|
<bucket_ptr, const bucket_info_t>::type const_bucket_info_ptr;
|
|||
|
typedef typename SlistImpl::size_type size_type;
|
|||
|
struct enabler {};
|
|||
|
|
|||
|
public:
|
|||
|
hashtable_iterator ()
|
|||
|
{}
|
|||
|
|
|||
|
explicit hashtable_iterator(local_iterator ptr, const_bucket_info_ptr bucket_info)
|
|||
|
: local_it_ (ptr), bucket_info_ (bucket_info)
|
|||
|
{}
|
|||
|
|
|||
|
template <class OtherValue>
|
|||
|
hashtable_iterator(hashtable_iterator<OtherValue, SlistImpl> const& other
|
|||
|
,typename boost::enable_if<
|
|||
|
boost::is_convertible<OtherValue*,Value*>
|
|||
|
, enabler
|
|||
|
>::type = enabler()
|
|||
|
)
|
|||
|
: local_it_(other.local_it_), bucket_info_(other.bucket_info_)
|
|||
|
{}
|
|||
|
|
|||
|
const local_iterator &local() const
|
|||
|
{ return local_it_; }
|
|||
|
|
|||
|
const_node_ptr pointed_node() const
|
|||
|
{ return local_it_.pointed_node(); }
|
|||
|
|
|||
|
const const_bucket_info_ptr &bucket_info() const
|
|||
|
{ return bucket_info_; }
|
|||
|
|
|||
|
private:
|
|||
|
friend class boost::iterator_core_access;
|
|||
|
template <class, class> friend class hashtable_iterator;
|
|||
|
|
|||
|
template <class OtherValue>
|
|||
|
bool equal(hashtable_iterator<OtherValue, SlistImpl> const& other) const
|
|||
|
{ return other.local() == local_it_; }
|
|||
|
|
|||
|
void increment()
|
|||
|
{
|
|||
|
using boost::get_pointer;
|
|||
|
size_type buckets_len = bucket_info_->buckets_len_;
|
|||
|
const_bucket_ptr buckets = bucket_info_->buckets_;
|
|||
|
const_local_iterator first = bucket_type::bucket_to_slist(buckets[0]).cend();
|
|||
|
const_local_iterator last = bucket_type::bucket_to_slist(buckets[buckets_len]).cend();
|
|||
|
|
|||
|
++local_it_;
|
|||
|
if(first.pointed_node() <= local_it_.pointed_node() &&
|
|||
|
local_it_.pointed_node() <= last.pointed_node()){
|
|||
|
size_type n_bucket = (size_type)
|
|||
|
bucket_type::get_bucket_num(local_it_, buckets[0], buckets[buckets_len]);
|
|||
|
do{
|
|||
|
if (++n_bucket == buckets_len){
|
|||
|
local_it_ = bucket_info_->buckets_->end();
|
|||
|
break;
|
|||
|
}
|
|||
|
local_it_ = bucket_type::bucket_to_slist(bucket_info_->buckets_[n_bucket]).begin();
|
|||
|
}
|
|||
|
while (local_it_ == bucket_type::bucket_to_slist(bucket_info_->buckets_[n_bucket]).end());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Value& dereference() const
|
|||
|
{ return *local_it_; }
|
|||
|
|
|||
|
local_iterator local_it_;
|
|||
|
const_bucket_info_ptr bucket_info_;
|
|||
|
};
|
|||
|
|
|||
|
} //namespace detail {
|
|||
|
} //namespace intrusive {
|
|||
|
} //namespace boost {
|
|||
|
|
|||
|
#endif
|