Chris@16: ///////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@101: // (C) Copyright Ion Gaztanaga 2007-2014 Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. Chris@16: // (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/intrusive for documentation. Chris@16: // Chris@16: ///////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: #ifndef BOOST_INTRUSIVE_HASHTABLE_NODE_HPP Chris@16: #define BOOST_INTRUSIVE_HASHTABLE_NODE_HPP Chris@16: Chris@101: #ifndef BOOST_CONFIG_HPP Chris@101: # include Chris@101: #endif Chris@101: Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@101: # pragma once Chris@101: #endif Chris@101: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include //make_slist Chris@16: #include Chris@101: #include Chris@16: #include Chris@16: Chris@16: Chris@16: namespace boost { Chris@16: namespace intrusive { Chris@16: namespace detail { Chris@16: Chris@16: template Chris@16: struct bucket_impl : public Slist Chris@16: { Chris@16: typedef Slist slist_type; Chris@16: bucket_impl() Chris@16: {} Chris@16: Chris@16: bucket_impl(const bucket_impl &) Chris@16: {} Chris@16: Chris@16: ~bucket_impl() Chris@16: { Chris@16: //This bucket is still being used! Chris@16: BOOST_INTRUSIVE_INVARIANT_ASSERT(Slist::empty()); Chris@16: } Chris@16: Chris@16: bucket_impl &operator=(const bucket_impl&) Chris@16: { Chris@16: //This bucket is still in use! Chris@16: BOOST_INTRUSIVE_INVARIANT_ASSERT(Slist::empty()); Chris@16: //Slist::clear(); Chris@16: return *this; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct bucket_traits_impl Chris@16: { Chris@16: private: Chris@16: BOOST_COPYABLE_AND_MOVABLE(bucket_traits_impl) Chris@16: Chris@16: public: Chris@16: /// @cond Chris@16: Chris@16: typedef typename pointer_traits Chris@16: ::template rebind_pointer Chris@16: < bucket_impl >::type bucket_ptr; Chris@16: typedef Slist slist; Chris@16: typedef typename Slist::size_type size_type; Chris@16: /// @endcond Chris@16: Chris@16: bucket_traits_impl(bucket_ptr buckets, size_type len) Chris@16: : buckets_(buckets), buckets_len_(len) Chris@16: {} Chris@16: Chris@16: bucket_traits_impl(const bucket_traits_impl &x) Chris@16: : buckets_(x.buckets_), buckets_len_(x.buckets_len_) Chris@16: {} Chris@16: Chris@16: bucket_traits_impl(BOOST_RV_REF(bucket_traits_impl) x) Chris@16: : buckets_(x.buckets_), buckets_len_(x.buckets_len_) Chris@16: { x.buckets_ = bucket_ptr(); x.buckets_len_ = 0; } Chris@16: Chris@16: bucket_traits_impl& operator=(BOOST_RV_REF(bucket_traits_impl) x) Chris@16: { Chris@16: buckets_ = x.buckets_; buckets_len_ = x.buckets_len_; Chris@16: x.buckets_ = bucket_ptr(); x.buckets_len_ = 0; return *this; Chris@16: } Chris@16: Chris@16: bucket_traits_impl& operator=(BOOST_COPY_ASSIGN_REF(bucket_traits_impl) x) Chris@16: { Chris@16: buckets_ = x.buckets_; buckets_len_ = x.buckets_len_; return *this; Chris@16: } Chris@16: Chris@16: const bucket_ptr &bucket_begin() const Chris@16: { return buckets_; } Chris@16: Chris@16: size_type bucket_count() const Chris@16: { return buckets_len_; } Chris@16: Chris@16: private: Chris@16: bucket_ptr buckets_; Chris@16: size_type buckets_len_; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct hash_reduced_slist_node_traits Chris@16: { Chris@16: template static detail::one test(...); Chris@16: template static detail::two test(typename U::reduced_slist_node_traits* = 0); Chris@16: static const bool value = sizeof(test(0)) == sizeof(detail::two); Chris@16: }; Chris@16: Chris@16: template Chris@16: struct apply_reduced_slist_node_traits Chris@16: { Chris@16: typedef typename NodeTraits::reduced_slist_node_traits type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct reduced_slist_node_traits Chris@16: { Chris@16: typedef typename detail::eval_if_c Chris@16: < hash_reduced_slist_node_traits::value Chris@16: , apply_reduced_slist_node_traits Chris@16: , detail::identity Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct get_slist_impl Chris@16: { Chris@16: typedef trivial_value_traits trivial_traits; Chris@16: Chris@16: //Reducing symbol length Chris@16: struct type : make_slist Chris@16: < typename NodeTraits::node Chris@16: , boost::intrusive::value_traits Chris@16: , boost::intrusive::constant_time_size Chris@101: , boost::intrusive::size_type Chris@16: >::type Chris@16: {}; Chris@16: }; Chris@16: Chris@16: } //namespace detail { Chris@16: Chris@16: template Chris@16: class hashtable_iterator Chris@101: { Chris@101: typedef boost::intrusive::iterator Chris@16: < std::forward_iterator_tag Chris@101: , typename BucketValueTraits::value_traits::value_type Chris@101: , typename pointer_traits::difference_type Chris@16: , typename detail::add_const_if_c Chris@101: ::type * Chris@16: , typename detail::add_const_if_c Chris@101: ::type & Chris@101: > iterator_traits; Chris@101: Chris@101: typedef typename BucketValueTraits::value_traits value_traits; Chris@101: typedef typename BucketValueTraits::bucket_traits bucket_traits; Chris@101: typedef typename value_traits::node_traits node_traits; Chris@16: typedef typename detail::get_slist_impl Chris@16: ::type Chris@16: >::type slist_impl; Chris@16: typedef typename slist_impl::iterator siterator; Chris@16: typedef typename slist_impl::const_iterator const_siterator; Chris@16: typedef detail::bucket_impl bucket_type; Chris@16: Chris@16: typedef typename pointer_traits Chris@101: ::template rebind_pointer Chris@16: < const BucketValueTraits >::type const_bucketvaltraits_ptr; Chris@16: typedef typename slist_impl::size_type size_type; Chris@16: Chris@16: Chris@16: static typename node_traits::node_ptr downcast_bucket(typename bucket_type::node_ptr p) Chris@16: { Chris@16: return pointer_traits:: Chris@16: pointer_to(static_cast(*p)); Chris@16: } Chris@16: Chris@16: public: Chris@101: typedef typename iterator_traits::difference_type difference_type; Chris@101: typedef typename iterator_traits::value_type value_type; Chris@101: typedef typename iterator_traits::pointer pointer; Chris@101: typedef typename iterator_traits::reference reference; Chris@101: typedef typename iterator_traits::iterator_category iterator_category; Chris@16: Chris@16: hashtable_iterator () Chris@101: : slist_it_() //Value initialization to achieve "null iterators" (N3644) Chris@16: {} Chris@16: Chris@16: explicit hashtable_iterator(siterator ptr, const BucketValueTraits *cont) Chris@16: : slist_it_ (ptr), traitsptr_ (cont ? pointer_traits::pointer_to(*cont) : const_bucketvaltraits_ptr() ) Chris@16: {} Chris@16: Chris@16: hashtable_iterator(const hashtable_iterator &other) Chris@16: : slist_it_(other.slist_it()), traitsptr_(other.get_bucket_value_traits()) Chris@16: {} Chris@16: Chris@16: const siterator &slist_it() const Chris@16: { return slist_it_; } Chris@16: Chris@16: hashtable_iterator unconst() const Chris@16: { return hashtable_iterator(this->slist_it(), this->get_bucket_value_traits()); } Chris@16: Chris@16: public: Chris@16: hashtable_iterator& operator++() Chris@16: { this->increment(); return *this; } Chris@16: Chris@16: hashtable_iterator operator++(int) Chris@16: { Chris@16: hashtable_iterator result (*this); Chris@16: this->increment(); Chris@16: return result; Chris@16: } Chris@16: Chris@16: friend bool operator== (const hashtable_iterator& i, const hashtable_iterator& i2) Chris@16: { return i.slist_it_ == i2.slist_it_; } Chris@16: Chris@16: friend bool operator!= (const hashtable_iterator& i, const hashtable_iterator& i2) Chris@16: { return !(i == i2); } Chris@16: Chris@16: reference operator*() const Chris@16: { return *this->operator ->(); } Chris@16: Chris@16: pointer operator->() const Chris@16: { Chris@101: return boost::intrusive::detail::to_raw_pointer(this->priv_value_traits().to_value_ptr Chris@16: (downcast_bucket(slist_it_.pointed_node()))); Chris@16: } Chris@16: Chris@16: const const_bucketvaltraits_ptr &get_bucket_value_traits() const Chris@16: { return traitsptr_; } Chris@16: Chris@101: const value_traits &priv_value_traits() const Chris@101: { return traitsptr_->priv_value_traits(); } Chris@16: Chris@101: const bucket_traits &priv_bucket_traits() const Chris@101: { return traitsptr_->priv_bucket_traits(); } Chris@16: Chris@16: private: Chris@16: void increment() Chris@16: { Chris@101: const bucket_traits &rbuck_traits = this->priv_bucket_traits(); Chris@16: bucket_type* const buckets = boost::intrusive::detail::to_raw_pointer(rbuck_traits.bucket_begin()); Chris@16: const size_type buckets_len = rbuck_traits.bucket_count(); Chris@16: Chris@16: ++slist_it_; Chris@16: const typename slist_impl::node_ptr n = slist_it_.pointed_node(); Chris@16: const siterator first_bucket_bbegin = buckets->end(); Chris@16: if(first_bucket_bbegin.pointed_node() <= n && n <= buckets[buckets_len-1].cend().pointed_node()){ Chris@16: //If one-past the node is inside the bucket then look for the next non-empty bucket Chris@16: //1. get the bucket_impl from the iterator Chris@16: const bucket_type &b = static_cast Chris@16: (bucket_type::slist_type::container_from_end_iterator(slist_it_)); Chris@16: Chris@16: //2. Now just calculate the index b has in the bucket array Chris@16: size_type n_bucket = static_cast(&b - buckets); Chris@16: Chris@16: //3. Iterate until a non-empty bucket is found Chris@16: do{ Chris@16: if (++n_bucket >= buckets_len){ //bucket overflow, return end() iterator Chris@16: slist_it_ = buckets->before_begin(); Chris@16: return; Chris@16: } Chris@16: } Chris@16: while (buckets[n_bucket].empty()); Chris@16: slist_it_ = buckets[n_bucket].begin(); Chris@16: } Chris@16: else{ Chris@16: //++slist_it_ yield to a valid object Chris@16: } Chris@16: } Chris@16: Chris@16: siterator slist_it_; Chris@16: const_bucketvaltraits_ptr traitsptr_; Chris@16: }; Chris@16: Chris@16: } //namespace intrusive { Chris@16: } //namespace boost { Chris@16: Chris@16: #endif