multiallocation_chain.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/container for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
  11. #define BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
  12. #ifndef BOOST_CONFIG_HPP
  13. # include <boost/config.hpp>
  14. #endif
  15. #if defined(BOOST_HAS_PRAGMA_ONCE)
  16. # pragma once
  17. #endif
  18. #include <boost/container/detail/config_begin.hpp>
  19. #include <boost/container/detail/workaround.hpp>
  20. // container
  21. #include <boost/container/container_fwd.hpp>
  22. // container/detail
  23. #include <boost/move/detail/to_raw_pointer.hpp>
  24. #include <boost/container/detail/type_traits.hpp>
  25. #include <boost/container/detail/placement_new.hpp>
  26. #include <boost/container/detail/iterator.hpp>
  27. // intrusive
  28. #include <boost/intrusive/slist.hpp>
  29. #include <boost/intrusive/pointer_traits.hpp>
  30. #include <boost/intrusive/detail/twin.hpp>
  31. // move
  32. #include <boost/move/utility_core.hpp>
  33. #include <boost/move/detail/iterator_to_raw_pointer.hpp>
  34. namespace boost {
  35. namespace container {
  36. namespace dtl {
  37. template<class VoidPointer>
  38. class basic_multiallocation_chain
  39. {
  40. private:
  41. typedef bi::slist_base_hook<bi::void_pointer<VoidPointer>
  42. ,bi::link_mode<bi::normal_link>
  43. > node;
  44. typedef typename boost::intrusive::pointer_traits
  45. <VoidPointer>::template rebind_pointer<char>::type char_ptr;
  46. typedef typename boost::intrusive::
  47. pointer_traits<char_ptr>::difference_type difference_type;
  48. typedef bi::slist< node
  49. , bi::linear<true>
  50. , bi::cache_last<true>
  51. , bi::size_type<typename boost::container::dtl::make_unsigned<difference_type>::type>
  52. > slist_impl_t;
  53. slist_impl_t slist_impl_;
  54. typedef typename boost::intrusive::pointer_traits
  55. <VoidPointer>::template rebind_pointer<node>::type node_ptr;
  56. typedef typename boost::intrusive::
  57. pointer_traits<node_ptr> node_ptr_traits;
  58. static node & to_node(const VoidPointer &p)
  59. { return *static_cast<node*>(static_cast<void*>(boost::movelib::to_raw_pointer(p))); }
  60. static VoidPointer from_node(node &n)
  61. { return node_ptr_traits::pointer_to(n); }
  62. static node_ptr to_node_ptr(const VoidPointer &p)
  63. { return node_ptr_traits::static_cast_from(p); }
  64. BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain)
  65. public:
  66. typedef VoidPointer void_pointer;
  67. typedef typename slist_impl_t::iterator iterator;
  68. typedef typename slist_impl_t::size_type size_type;
  69. typedef boost::intrusive::twin<void_pointer> pointer_pair;
  70. basic_multiallocation_chain()
  71. : slist_impl_()
  72. {}
  73. basic_multiallocation_chain(const void_pointer &b, const void_pointer &before_e, size_type n)
  74. : slist_impl_(to_node_ptr(b), to_node_ptr(before_e), n)
  75. {}
  76. basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other)
  77. : slist_impl_(::boost::move(other.slist_impl_))
  78. {}
  79. basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other)
  80. {
  81. slist_impl_ = ::boost::move(other.slist_impl_);
  82. return *this;
  83. }
  84. bool empty() const
  85. { return slist_impl_.empty(); }
  86. size_type size() const
  87. { return slist_impl_.size(); }
  88. iterator before_begin()
  89. { return slist_impl_.before_begin(); }
  90. iterator begin()
  91. { return slist_impl_.begin(); }
  92. iterator end()
  93. { return slist_impl_.end(); }
  94. iterator last()
  95. { return slist_impl_.last(); }
  96. void clear()
  97. { slist_impl_.clear(); }
  98. iterator insert_after(iterator it, void_pointer m)
  99. { return slist_impl_.insert_after(it, to_node(m)); }
  100. void push_front(const void_pointer &m)
  101. { return slist_impl_.push_front(to_node(m)); }
  102. void push_back(const void_pointer &m)
  103. { return slist_impl_.push_back(to_node(m)); }
  104. void_pointer pop_front()
  105. {
  106. node & n = slist_impl_.front();
  107. void_pointer ret = from_node(n);
  108. slist_impl_.pop_front();
  109. return ret;
  110. }
  111. void splice_after(iterator after_this, basic_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
  112. { slist_impl_.splice_after(after_this, x.slist_impl_, before_b, before_e, n); }
  113. void splice_after(iterator after_this, basic_multiallocation_chain &x)
  114. { slist_impl_.splice_after(after_this, x.slist_impl_); }
  115. void erase_after(iterator before_b, iterator e, size_type n)
  116. { slist_impl_.erase_after(before_b, e, n); }
  117. void_pointer incorporate_after(iterator after_this, const void_pointer &b, size_type unit_bytes, size_type num_units)
  118. {
  119. typedef typename boost::intrusive::pointer_traits<char_ptr> char_pointer_traits;
  120. char_ptr elem = char_pointer_traits::static_cast_from(b);
  121. if(num_units){
  122. char_ptr prev_elem = elem;
  123. elem += difference_type(unit_bytes);
  124. for(size_type i = 0; i != num_units-1u; ++i, elem += difference_type(unit_bytes)){
  125. ::new (boost::movelib::to_raw_pointer(prev_elem), boost_container_new_t()) void_pointer(elem);
  126. prev_elem = elem;
  127. }
  128. slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(prev_elem), num_units);
  129. }
  130. return elem;
  131. }
  132. void incorporate_after(iterator after_this, void_pointer b, void_pointer before_e, size_type n)
  133. { slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(before_e), n); }
  134. void swap(basic_multiallocation_chain &x)
  135. { slist_impl_.swap(x.slist_impl_); }
  136. static iterator iterator_to(const void_pointer &p)
  137. { return slist_impl_t::s_iterator_to(to_node(p)); }
  138. pointer_pair extract_data()
  139. {
  140. if(BOOST_LIKELY(!slist_impl_.empty())){
  141. pointer_pair ret
  142. (slist_impl_.begin().operator->()
  143. ,slist_impl_.last().operator->());
  144. slist_impl_.clear();
  145. return ret;
  146. }
  147. else {
  148. return pointer_pair();
  149. }
  150. }
  151. };
  152. template <class Iterator, class T>
  153. class multialloc_iterator
  154. : public boost::container::iterator
  155. < typename Iterator::iterator_category
  156. , T
  157. , typename Iterator::difference_type
  158. , T*
  159. , T&
  160. >
  161. {
  162. public:
  163. inline explicit multialloc_iterator(const Iterator &it)
  164. : m_it(it)
  165. {}
  166. inline explicit multialloc_iterator()
  167. : m_it()
  168. {}
  169. //Constructors
  170. inline multialloc_iterator& operator++()
  171. { increment(); return *this; }
  172. inline multialloc_iterator operator++(int)
  173. {
  174. multialloc_iterator result (*this);
  175. increment();
  176. return result;
  177. }
  178. inline friend bool operator== (const multialloc_iterator& i, const multialloc_iterator& i2)
  179. { return i.equal(i2); }
  180. inline friend bool operator!= (const multialloc_iterator& i, const multialloc_iterator& i2)
  181. { return !(i == i2); }
  182. inline friend typename Iterator::difference_type operator- (const multialloc_iterator& i, const multialloc_iterator& i2)
  183. { return i2.distance_to(i); }
  184. //Arithmetic
  185. inline multialloc_iterator& operator+=(typename Iterator::difference_type off)
  186. { this->advance(off); return *this; }
  187. inline multialloc_iterator operator+(typename Iterator::difference_type off) const
  188. {
  189. multialloc_iterator other(*this);
  190. other.advance(off);
  191. return other;
  192. }
  193. inline friend multialloc_iterator operator+(typename Iterator::difference_type off, const multialloc_iterator& right)
  194. { return right + off; }
  195. inline multialloc_iterator& operator-=(typename Iterator::difference_type off)
  196. { this->advance(-off); return *this; }
  197. inline multialloc_iterator operator-(typename Iterator::difference_type off) const
  198. { return *this + (-off); }
  199. inline T& operator*() const
  200. { return *this->operator->(); }
  201. inline T* operator->() const
  202. { return static_cast<T*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(m_it))); }
  203. inline Iterator & base()
  204. { return m_it; }
  205. inline const Iterator & base() const
  206. { return m_it; }
  207. private:
  208. Iterator m_it;
  209. inline void increment()
  210. { ++m_it; }
  211. inline void decrement()
  212. { --m_it; }
  213. inline bool equal(const multialloc_iterator &other) const
  214. { return m_it == other.m_it; }
  215. inline bool less(const multialloc_iterator &other) const
  216. { return other.m_it < m_it; }
  217. inline void advance(typename Iterator::difference_type n)
  218. { boost::container::iterator_advance(m_it, n); }
  219. inline typename Iterator::difference_type distance_to(const multialloc_iterator &other)const
  220. { return boost::container::iterator_distance(other.m_it, m_it); }
  221. };
  222. template<class MultiallocationChain, class T>
  223. class transform_multiallocation_chain
  224. : public MultiallocationChain
  225. {
  226. private:
  227. BOOST_MOVABLE_BUT_NOT_COPYABLE(transform_multiallocation_chain)
  228. //transform_multiallocation_chain(const transform_multiallocation_chain &);
  229. //transform_multiallocation_chain & operator=(const transform_multiallocation_chain &);
  230. typedef typename MultiallocationChain::void_pointer void_pointer;
  231. typedef typename boost::intrusive::pointer_traits
  232. <void_pointer> void_pointer_traits;
  233. typedef typename void_pointer_traits::template
  234. rebind_pointer<T>::type pointer;
  235. typedef typename boost::intrusive::pointer_traits
  236. <pointer> pointer_traits;
  237. static pointer cast(const void_pointer &p)
  238. { return pointer_traits::static_cast_from(p); }
  239. public:
  240. typedef multialloc_iterator
  241. <typename MultiallocationChain::iterator, T> iterator;
  242. typedef typename MultiallocationChain::size_type size_type;
  243. typedef boost::intrusive::twin<pointer> pointer_pair;
  244. transform_multiallocation_chain()
  245. : MultiallocationChain()
  246. {}
  247. transform_multiallocation_chain(BOOST_RV_REF(transform_multiallocation_chain) other)
  248. : MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
  249. {}
  250. transform_multiallocation_chain(BOOST_RV_REF(MultiallocationChain) other)
  251. : MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
  252. {}
  253. transform_multiallocation_chain& operator=(BOOST_RV_REF(transform_multiallocation_chain) other)
  254. {
  255. return static_cast<MultiallocationChain&>
  256. (this->MultiallocationChain::operator=(::boost::move(static_cast<MultiallocationChain&>(other))));
  257. }
  258. void push_front(const pointer &mem)
  259. { this->MultiallocationChain::push_front(mem); }
  260. void push_back(const pointer &mem)
  261. { return this->MultiallocationChain::push_back(mem); }
  262. void swap(transform_multiallocation_chain &other_chain)
  263. { this->MultiallocationChain::swap(other_chain); }
  264. void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
  265. { this->MultiallocationChain::splice_after(after_this.base(), x, before_b.base(), before_e.base(), n); }
  266. void incorporate_after(iterator after_this, pointer b, pointer before_e, size_type n)
  267. { this->MultiallocationChain::incorporate_after(after_this.base(), b, before_e, n); }
  268. pointer pop_front()
  269. { return cast(this->MultiallocationChain::pop_front()); }
  270. bool empty() const
  271. { return this->MultiallocationChain::empty(); }
  272. iterator before_begin()
  273. { return iterator(this->MultiallocationChain::before_begin()); }
  274. iterator begin()
  275. { return iterator(this->MultiallocationChain::begin()); }
  276. iterator last()
  277. { return iterator(this->MultiallocationChain::last()); }
  278. iterator end()
  279. { return iterator(this->MultiallocationChain::end()); }
  280. size_type size() const
  281. { return this->MultiallocationChain::size(); }
  282. void clear()
  283. { this->MultiallocationChain::clear(); }
  284. iterator insert_after(iterator it, pointer m)
  285. { return iterator(this->MultiallocationChain::insert_after(it.base(), m)); }
  286. static iterator iterator_to(const pointer &p)
  287. { return iterator(MultiallocationChain::iterator_to(p)); }
  288. pointer_pair extract_data()
  289. {
  290. typename MultiallocationChain::pointer_pair data(this->MultiallocationChain::extract_data());
  291. return pointer_pair(cast(data.first), cast(data.second));
  292. }
  293. /*
  294. MultiallocationChain &extract_multiallocation_chain()
  295. { return holder_; }*/
  296. };
  297. }}}
  298. // namespace dtl {
  299. // namespace container {
  300. // namespace boost {
  301. #include <boost/container/detail/config_end.hpp>
  302. #endif //BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP