hashtable_node.hpp 13 KB

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