annotate DEPENDENCIES/generic/include/boost/intrusive/detail/hashtable_node.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 /////////////////////////////////////////////////////////////////////////////
Chris@16 2 //
Chris@101 3 // (C) Copyright Ion Gaztanaga 2007-2014
Chris@16 4 //
Chris@16 5 // Distributed under the Boost Software License, Version 1.0.
Chris@16 6 // (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8 //
Chris@16 9 // See http://www.boost.org/libs/intrusive for documentation.
Chris@16 10 //
Chris@16 11 /////////////////////////////////////////////////////////////////////////////
Chris@16 12
Chris@16 13 #ifndef BOOST_INTRUSIVE_HASHTABLE_NODE_HPP
Chris@16 14 #define BOOST_INTRUSIVE_HASHTABLE_NODE_HPP
Chris@16 15
Chris@101 16 #ifndef BOOST_CONFIG_HPP
Chris@101 17 # include <boost/config.hpp>
Chris@101 18 #endif
Chris@101 19
Chris@101 20 #if defined(BOOST_HAS_PRAGMA_ONCE)
Chris@101 21 # pragma once
Chris@101 22 #endif
Chris@101 23
Chris@16 24 #include <boost/intrusive/detail/assert.hpp>
Chris@16 25 #include <boost/intrusive/pointer_traits.hpp>
Chris@16 26 #include <boost/intrusive/detail/mpl.hpp>
Chris@16 27 #include <boost/intrusive/trivial_value_traits.hpp>
Chris@101 28 #include <boost/intrusive/slist.hpp> //make_slist
Chris@16 29 #include <cstddef>
Chris@101 30 #include <climits>
Chris@16 31 #include <boost/move/core.hpp>
Chris@16 32
Chris@16 33
Chris@16 34 namespace boost {
Chris@16 35 namespace intrusive {
Chris@16 36 namespace detail {
Chris@16 37
Chris@16 38 template <class Slist>
Chris@16 39 struct bucket_impl : public Slist
Chris@16 40 {
Chris@16 41 typedef Slist slist_type;
Chris@16 42 bucket_impl()
Chris@16 43 {}
Chris@16 44
Chris@16 45 bucket_impl(const bucket_impl &)
Chris@16 46 {}
Chris@16 47
Chris@16 48 ~bucket_impl()
Chris@16 49 {
Chris@16 50 //This bucket is still being used!
Chris@16 51 BOOST_INTRUSIVE_INVARIANT_ASSERT(Slist::empty());
Chris@16 52 }
Chris@16 53
Chris@16 54 bucket_impl &operator=(const bucket_impl&)
Chris@16 55 {
Chris@16 56 //This bucket is still in use!
Chris@16 57 BOOST_INTRUSIVE_INVARIANT_ASSERT(Slist::empty());
Chris@16 58 //Slist::clear();
Chris@16 59 return *this;
Chris@16 60 }
Chris@16 61 };
Chris@16 62
Chris@16 63 template<class Slist>
Chris@16 64 struct bucket_traits_impl
Chris@16 65 {
Chris@16 66 private:
Chris@16 67 BOOST_COPYABLE_AND_MOVABLE(bucket_traits_impl)
Chris@16 68
Chris@16 69 public:
Chris@16 70 /// @cond
Chris@16 71
Chris@16 72 typedef typename pointer_traits
Chris@16 73 <typename Slist::pointer>::template rebind_pointer
Chris@16 74 < bucket_impl<Slist> >::type bucket_ptr;
Chris@16 75 typedef Slist slist;
Chris@16 76 typedef typename Slist::size_type size_type;
Chris@16 77 /// @endcond
Chris@16 78
Chris@16 79 bucket_traits_impl(bucket_ptr buckets, size_type len)
Chris@16 80 : buckets_(buckets), buckets_len_(len)
Chris@16 81 {}
Chris@16 82
Chris@16 83 bucket_traits_impl(const bucket_traits_impl &x)
Chris@16 84 : buckets_(x.buckets_), buckets_len_(x.buckets_len_)
Chris@16 85 {}
Chris@16 86
Chris@16 87 bucket_traits_impl(BOOST_RV_REF(bucket_traits_impl) x)
Chris@16 88 : buckets_(x.buckets_), buckets_len_(x.buckets_len_)
Chris@16 89 { x.buckets_ = bucket_ptr(); x.buckets_len_ = 0; }
Chris@16 90
Chris@16 91 bucket_traits_impl& operator=(BOOST_RV_REF(bucket_traits_impl) x)
Chris@16 92 {
Chris@16 93 buckets_ = x.buckets_; buckets_len_ = x.buckets_len_;
Chris@16 94 x.buckets_ = bucket_ptr(); x.buckets_len_ = 0; return *this;
Chris@16 95 }
Chris@16 96
Chris@16 97 bucket_traits_impl& operator=(BOOST_COPY_ASSIGN_REF(bucket_traits_impl) x)
Chris@16 98 {
Chris@16 99 buckets_ = x.buckets_; buckets_len_ = x.buckets_len_; return *this;
Chris@16 100 }
Chris@16 101
Chris@16 102 const bucket_ptr &bucket_begin() const
Chris@16 103 { return buckets_; }
Chris@16 104
Chris@16 105 size_type bucket_count() const
Chris@16 106 { return buckets_len_; }
Chris@16 107
Chris@16 108 private:
Chris@16 109 bucket_ptr buckets_;
Chris@16 110 size_type buckets_len_;
Chris@16 111 };
Chris@16 112
Chris@16 113 template <class NodeTraits>
Chris@16 114 struct hash_reduced_slist_node_traits
Chris@16 115 {
Chris@16 116 template <class U> static detail::one test(...);
Chris@16 117 template <class U> static detail::two test(typename U::reduced_slist_node_traits* = 0);
Chris@16 118 static const bool value = sizeof(test<NodeTraits>(0)) == sizeof(detail::two);
Chris@16 119 };
Chris@16 120
Chris@16 121 template <class NodeTraits>
Chris@16 122 struct apply_reduced_slist_node_traits
Chris@16 123 {
Chris@16 124 typedef typename NodeTraits::reduced_slist_node_traits type;
Chris@16 125 };
Chris@16 126
Chris@16 127 template <class NodeTraits>
Chris@16 128 struct reduced_slist_node_traits
Chris@16 129 {
Chris@16 130 typedef typename detail::eval_if_c
Chris@16 131 < hash_reduced_slist_node_traits<NodeTraits>::value
Chris@16 132 , apply_reduced_slist_node_traits<NodeTraits>
Chris@16 133 , detail::identity<NodeTraits>
Chris@16 134 >::type type;
Chris@16 135 };
Chris@16 136
Chris@16 137 template<class NodeTraits>
Chris@16 138 struct get_slist_impl
Chris@16 139 {
Chris@16 140 typedef trivial_value_traits<NodeTraits, normal_link> trivial_traits;
Chris@16 141
Chris@16 142 //Reducing symbol length
Chris@16 143 struct type : make_slist
Chris@16 144 < typename NodeTraits::node
Chris@16 145 , boost::intrusive::value_traits<trivial_traits>
Chris@16 146 , boost::intrusive::constant_time_size<false>
Chris@101 147 , boost::intrusive::size_type<std::size_t>
Chris@16 148 >::type
Chris@16 149 {};
Chris@16 150 };
Chris@16 151
Chris@16 152 } //namespace detail {
Chris@16 153
Chris@16 154 template<class BucketValueTraits, bool IsConst>
Chris@16 155 class hashtable_iterator
Chris@101 156 {
Chris@101 157 typedef boost::intrusive::iterator
Chris@16 158 < std::forward_iterator_tag
Chris@101 159 , typename BucketValueTraits::value_traits::value_type
Chris@101 160 , typename pointer_traits<typename BucketValueTraits::value_traits::value_type*>::difference_type
Chris@16 161 , typename detail::add_const_if_c
Chris@101 162 <typename BucketValueTraits::value_traits::value_type, IsConst>::type *
Chris@16 163 , typename detail::add_const_if_c
Chris@101 164 <typename BucketValueTraits::value_traits::value_type, IsConst>::type &
Chris@101 165 > iterator_traits;
Chris@101 166
Chris@101 167 typedef typename BucketValueTraits::value_traits value_traits;
Chris@101 168 typedef typename BucketValueTraits::bucket_traits bucket_traits;
Chris@101 169 typedef typename value_traits::node_traits node_traits;
Chris@16 170 typedef typename detail::get_slist_impl
Chris@16 171 <typename detail::reduced_slist_node_traits
Chris@101 172 <typename value_traits::node_traits>::type
Chris@16 173 >::type slist_impl;
Chris@16 174 typedef typename slist_impl::iterator siterator;
Chris@16 175 typedef typename slist_impl::const_iterator const_siterator;
Chris@16 176 typedef detail::bucket_impl<slist_impl> bucket_type;
Chris@16 177
Chris@16 178 typedef typename pointer_traits
Chris@101 179 <typename value_traits::pointer>::template rebind_pointer
Chris@16 180 < const BucketValueTraits >::type const_bucketvaltraits_ptr;
Chris@16 181 typedef typename slist_impl::size_type size_type;
Chris@16 182
Chris@16 183
Chris@16 184 static typename node_traits::node_ptr downcast_bucket(typename bucket_type::node_ptr p)
Chris@16 185 {
Chris@16 186 return pointer_traits<typename node_traits::node_ptr>::
Chris@16 187 pointer_to(static_cast<typename node_traits::node&>(*p));
Chris@16 188 }
Chris@16 189
Chris@16 190 public:
Chris@101 191 typedef typename iterator_traits::difference_type difference_type;
Chris@101 192 typedef typename iterator_traits::value_type value_type;
Chris@101 193 typedef typename iterator_traits::pointer pointer;
Chris@101 194 typedef typename iterator_traits::reference reference;
Chris@101 195 typedef typename iterator_traits::iterator_category iterator_category;
Chris@16 196
Chris@16 197 hashtable_iterator ()
Chris@101 198 : slist_it_() //Value initialization to achieve "null iterators" (N3644)
Chris@16 199 {}
Chris@16 200
Chris@16 201 explicit hashtable_iterator(siterator ptr, const BucketValueTraits *cont)
Chris@16 202 : slist_it_ (ptr), traitsptr_ (cont ? pointer_traits<const_bucketvaltraits_ptr>::pointer_to(*cont) : const_bucketvaltraits_ptr() )
Chris@16 203 {}
Chris@16 204
Chris@16 205 hashtable_iterator(const hashtable_iterator<BucketValueTraits, false> &other)
Chris@16 206 : slist_it_(other.slist_it()), traitsptr_(other.get_bucket_value_traits())
Chris@16 207 {}
Chris@16 208
Chris@16 209 const siterator &slist_it() const
Chris@16 210 { return slist_it_; }
Chris@16 211
Chris@16 212 hashtable_iterator<BucketValueTraits, false> unconst() const
Chris@16 213 { return hashtable_iterator<BucketValueTraits, false>(this->slist_it(), this->get_bucket_value_traits()); }
Chris@16 214
Chris@16 215 public:
Chris@16 216 hashtable_iterator& operator++()
Chris@16 217 { this->increment(); return *this; }
Chris@16 218
Chris@16 219 hashtable_iterator operator++(int)
Chris@16 220 {
Chris@16 221 hashtable_iterator result (*this);
Chris@16 222 this->increment();
Chris@16 223 return result;
Chris@16 224 }
Chris@16 225
Chris@16 226 friend bool operator== (const hashtable_iterator& i, const hashtable_iterator& i2)
Chris@16 227 { return i.slist_it_ == i2.slist_it_; }
Chris@16 228
Chris@16 229 friend bool operator!= (const hashtable_iterator& i, const hashtable_iterator& i2)
Chris@16 230 { return !(i == i2); }
Chris@16 231
Chris@16 232 reference operator*() const
Chris@16 233 { return *this->operator ->(); }
Chris@16 234
Chris@16 235 pointer operator->() const
Chris@16 236 {
Chris@101 237 return boost::intrusive::detail::to_raw_pointer(this->priv_value_traits().to_value_ptr
Chris@16 238 (downcast_bucket(slist_it_.pointed_node())));
Chris@16 239 }
Chris@16 240
Chris@16 241 const const_bucketvaltraits_ptr &get_bucket_value_traits() const
Chris@16 242 { return traitsptr_; }
Chris@16 243
Chris@101 244 const value_traits &priv_value_traits() const
Chris@101 245 { return traitsptr_->priv_value_traits(); }
Chris@16 246
Chris@101 247 const bucket_traits &priv_bucket_traits() const
Chris@101 248 { return traitsptr_->priv_bucket_traits(); }
Chris@16 249
Chris@16 250 private:
Chris@16 251 void increment()
Chris@16 252 {
Chris@101 253 const bucket_traits &rbuck_traits = this->priv_bucket_traits();
Chris@16 254 bucket_type* const buckets = boost::intrusive::detail::to_raw_pointer(rbuck_traits.bucket_begin());
Chris@16 255 const size_type buckets_len = rbuck_traits.bucket_count();
Chris@16 256
Chris@16 257 ++slist_it_;
Chris@16 258 const typename slist_impl::node_ptr n = slist_it_.pointed_node();
Chris@16 259 const siterator first_bucket_bbegin = buckets->end();
Chris@16 260 if(first_bucket_bbegin.pointed_node() <= n && n <= buckets[buckets_len-1].cend().pointed_node()){
Chris@16 261 //If one-past the node is inside the bucket then look for the next non-empty bucket
Chris@16 262 //1. get the bucket_impl from the iterator
Chris@16 263 const bucket_type &b = static_cast<const bucket_type&>
Chris@16 264 (bucket_type::slist_type::container_from_end_iterator(slist_it_));
Chris@16 265
Chris@16 266 //2. Now just calculate the index b has in the bucket array
Chris@16 267 size_type n_bucket = static_cast<size_type>(&b - buckets);
Chris@16 268
Chris@16 269 //3. Iterate until a non-empty bucket is found
Chris@16 270 do{
Chris@16 271 if (++n_bucket >= buckets_len){ //bucket overflow, return end() iterator
Chris@16 272 slist_it_ = buckets->before_begin();
Chris@16 273 return;
Chris@16 274 }
Chris@16 275 }
Chris@16 276 while (buckets[n_bucket].empty());
Chris@16 277 slist_it_ = buckets[n_bucket].begin();
Chris@16 278 }
Chris@16 279 else{
Chris@16 280 //++slist_it_ yield to a valid object
Chris@16 281 }
Chris@16 282 }
Chris@16 283
Chris@16 284 siterator slist_it_;
Chris@16 285 const_bucketvaltraits_ptr traitsptr_;
Chris@16 286 };
Chris@16 287
Chris@16 288 } //namespace intrusive {
Chris@16 289 } //namespace boost {
Chris@16 290
Chris@16 291 #endif