multiallocation_chain.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  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/transform_iterator.hpp>
  25. #include <boost/container/detail/type_traits.hpp>
  26. #include <boost/container/detail/placement_new.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. namespace boost {
  34. namespace container {
  35. namespace dtl {
  36. template<class VoidPointer>
  37. class basic_multiallocation_chain
  38. {
  39. private:
  40. typedef bi::slist_base_hook<bi::void_pointer<VoidPointer>
  41. ,bi::link_mode<bi::normal_link>
  42. > node;
  43. typedef typename boost::intrusive::pointer_traits
  44. <VoidPointer>::template rebind_pointer<char>::type char_ptr;
  45. typedef typename boost::intrusive::
  46. pointer_traits<char_ptr>::difference_type difference_type;
  47. typedef bi::slist< node
  48. , bi::linear<true>
  49. , bi::cache_last<true>
  50. , bi::size_type<typename boost::container::dtl::make_unsigned<difference_type>::type>
  51. > slist_impl_t;
  52. slist_impl_t slist_impl_;
  53. typedef typename boost::intrusive::pointer_traits
  54. <VoidPointer>::template rebind_pointer<node>::type node_ptr;
  55. typedef typename boost::intrusive::
  56. pointer_traits<node_ptr> node_ptr_traits;
  57. static node & to_node(const VoidPointer &p)
  58. { return *static_cast<node*>(static_cast<void*>(boost::movelib::to_raw_pointer(p))); }
  59. static VoidPointer from_node(node &n)
  60. { return node_ptr_traits::pointer_to(n); }
  61. static node_ptr to_node_ptr(const VoidPointer &p)
  62. { return node_ptr_traits::static_cast_from(p); }
  63. BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain)
  64. public:
  65. typedef VoidPointer void_pointer;
  66. typedef typename slist_impl_t::iterator iterator;
  67. typedef typename slist_impl_t::size_type size_type;
  68. typedef boost::intrusive::twin<void_pointer> pointer_pair;
  69. basic_multiallocation_chain()
  70. : slist_impl_()
  71. {}
  72. basic_multiallocation_chain(const void_pointer &b, const void_pointer &before_e, size_type n)
  73. : slist_impl_(to_node_ptr(b), to_node_ptr(before_e), n)
  74. {}
  75. basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other)
  76. : slist_impl_(::boost::move(other.slist_impl_))
  77. {}
  78. basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other)
  79. {
  80. slist_impl_ = ::boost::move(other.slist_impl_);
  81. return *this;
  82. }
  83. bool empty() const
  84. { return slist_impl_.empty(); }
  85. size_type size() const
  86. { return slist_impl_.size(); }
  87. iterator before_begin()
  88. { return slist_impl_.before_begin(); }
  89. iterator begin()
  90. { return slist_impl_.begin(); }
  91. iterator end()
  92. { return slist_impl_.end(); }
  93. iterator last()
  94. { return slist_impl_.last(); }
  95. void clear()
  96. { slist_impl_.clear(); }
  97. iterator insert_after(iterator it, void_pointer m)
  98. { return slist_impl_.insert_after(it, to_node(m)); }
  99. void push_front(const void_pointer &m)
  100. { return slist_impl_.push_front(to_node(m)); }
  101. void push_back(const void_pointer &m)
  102. { return slist_impl_.push_back(to_node(m)); }
  103. void_pointer pop_front()
  104. {
  105. node & n = slist_impl_.front();
  106. void_pointer ret = from_node(n);
  107. slist_impl_.pop_front();
  108. return ret;
  109. }
  110. void splice_after(iterator after_this, basic_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
  111. { slist_impl_.splice_after(after_this, x.slist_impl_, before_b, before_e, n); }
  112. void splice_after(iterator after_this, basic_multiallocation_chain &x)
  113. { slist_impl_.splice_after(after_this, x.slist_impl_); }
  114. void erase_after(iterator before_b, iterator e, size_type n)
  115. { slist_impl_.erase_after(before_b, e, n); }
  116. void_pointer incorporate_after(iterator after_this, const void_pointer &b, size_type unit_bytes, size_type num_units)
  117. {
  118. typedef typename boost::intrusive::pointer_traits<char_ptr> char_pointer_traits;
  119. char_ptr elem = char_pointer_traits::static_cast_from(b);
  120. if(num_units){
  121. char_ptr prev_elem = elem;
  122. elem += difference_type(unit_bytes);
  123. for(size_type i = 0; i != num_units-1u; ++i, elem += difference_type(unit_bytes)){
  124. ::new (boost::movelib::to_raw_pointer(prev_elem), boost_container_new_t()) void_pointer(elem);
  125. prev_elem = elem;
  126. }
  127. slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(prev_elem), num_units);
  128. }
  129. return elem;
  130. }
  131. void incorporate_after(iterator after_this, void_pointer b, void_pointer before_e, size_type n)
  132. { slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(before_e), n); }
  133. void swap(basic_multiallocation_chain &x)
  134. { slist_impl_.swap(x.slist_impl_); }
  135. static iterator iterator_to(const void_pointer &p)
  136. { return slist_impl_t::s_iterator_to(to_node(p)); }
  137. pointer_pair extract_data()
  138. {
  139. if(BOOST_LIKELY(!slist_impl_.empty())){
  140. pointer_pair ret
  141. (slist_impl_.begin().operator->()
  142. ,slist_impl_.last().operator->());
  143. slist_impl_.clear();
  144. return ret;
  145. }
  146. else {
  147. return pointer_pair();
  148. }
  149. }
  150. };
  151. template<class T>
  152. struct cast_functor
  153. {
  154. typedef typename dtl::add_reference<T>::type result_type;
  155. template<class U>
  156. result_type operator()(U &ptr) const
  157. { return *static_cast<T*>(static_cast<void*>(&ptr)); }
  158. };
  159. template<class MultiallocationChain, class T>
  160. class transform_multiallocation_chain
  161. : public MultiallocationChain
  162. {
  163. private:
  164. BOOST_MOVABLE_BUT_NOT_COPYABLE(transform_multiallocation_chain)
  165. //transform_multiallocation_chain(const transform_multiallocation_chain &);
  166. //transform_multiallocation_chain & operator=(const transform_multiallocation_chain &);
  167. typedef typename MultiallocationChain::void_pointer void_pointer;
  168. typedef typename boost::intrusive::pointer_traits
  169. <void_pointer> void_pointer_traits;
  170. typedef typename void_pointer_traits::template
  171. rebind_pointer<T>::type pointer;
  172. typedef typename boost::intrusive::pointer_traits
  173. <pointer> pointer_traits;
  174. static pointer cast(const void_pointer &p)
  175. { return pointer_traits::static_cast_from(p); }
  176. public:
  177. typedef transform_iterator
  178. < typename MultiallocationChain::iterator
  179. , dtl::cast_functor <T> > iterator;
  180. typedef typename MultiallocationChain::size_type size_type;
  181. typedef boost::intrusive::twin<pointer> pointer_pair;
  182. transform_multiallocation_chain()
  183. : MultiallocationChain()
  184. {}
  185. transform_multiallocation_chain(BOOST_RV_REF(transform_multiallocation_chain) other)
  186. : MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
  187. {}
  188. transform_multiallocation_chain(BOOST_RV_REF(MultiallocationChain) other)
  189. : MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
  190. {}
  191. transform_multiallocation_chain& operator=(BOOST_RV_REF(transform_multiallocation_chain) other)
  192. {
  193. return static_cast<MultiallocationChain&>
  194. (this->MultiallocationChain::operator=(::boost::move(static_cast<MultiallocationChain&>(other))));
  195. }
  196. void push_front(const pointer &mem)
  197. { this->MultiallocationChain::push_front(mem); }
  198. void push_back(const pointer &mem)
  199. { return this->MultiallocationChain::push_back(mem); }
  200. void swap(transform_multiallocation_chain &other_chain)
  201. { this->MultiallocationChain::swap(other_chain); }
  202. void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
  203. { this->MultiallocationChain::splice_after(after_this.base(), x, before_b.base(), before_e.base(), n); }
  204. void incorporate_after(iterator after_this, pointer b, pointer before_e, size_type n)
  205. { this->MultiallocationChain::incorporate_after(after_this.base(), b, before_e, n); }
  206. pointer pop_front()
  207. { return cast(this->MultiallocationChain::pop_front()); }
  208. bool empty() const
  209. { return this->MultiallocationChain::empty(); }
  210. iterator before_begin()
  211. { return iterator(this->MultiallocationChain::before_begin()); }
  212. iterator begin()
  213. { return iterator(this->MultiallocationChain::begin()); }
  214. iterator last()
  215. { return iterator(this->MultiallocationChain::last()); }
  216. iterator end()
  217. { return iterator(this->MultiallocationChain::end()); }
  218. size_type size() const
  219. { return this->MultiallocationChain::size(); }
  220. void clear()
  221. { this->MultiallocationChain::clear(); }
  222. iterator insert_after(iterator it, pointer m)
  223. { return iterator(this->MultiallocationChain::insert_after(it.base(), m)); }
  224. static iterator iterator_to(const pointer &p)
  225. { return iterator(MultiallocationChain::iterator_to(p)); }
  226. pointer_pair extract_data()
  227. {
  228. typename MultiallocationChain::pointer_pair data(this->MultiallocationChain::extract_data());
  229. return pointer_pair(cast(data.first), cast(data.second));
  230. }
  231. /*
  232. MultiallocationChain &extract_multiallocation_chain()
  233. { return holder_; }*/
  234. };
  235. }}}
  236. // namespace dtl {
  237. // namespace container {
  238. // namespace boost {
  239. #include <boost/container/detail/config_end.hpp>
  240. #endif //BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP