destroyers.hpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2013.
  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/container for documentation.
  10. //
  11. //////////////////////////////////////////////////////////////////////////////
  12. #ifndef BOOST_CONTAINER_DESTROYERS_HPP
  13. #define BOOST_CONTAINER_DESTROYERS_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/container/detail/config_begin.hpp>
  21. #include <boost/container/detail/workaround.hpp>
  22. #include <boost/container/allocator_traits.hpp>
  23. #include <boost/move/detail/to_raw_pointer.hpp>
  24. #include <boost/container/detail/version_type.hpp>
  25. namespace boost {
  26. namespace container {
  27. namespace dtl {
  28. //!A deleter for scoped_ptr that deallocates the memory
  29. //!allocated for an object using a STL allocator.
  30. template <class Allocator>
  31. struct scoped_deallocator
  32. {
  33. typedef allocator_traits<Allocator> allocator_traits_type;
  34. typedef typename allocator_traits_type::pointer pointer;
  35. typedef dtl::integral_constant<unsigned,
  36. boost::container::dtl::
  37. version<Allocator>::value> alloc_version;
  38. private:
  39. void priv_deallocate(version_1)
  40. { m_alloc.deallocate(m_ptr, 1); }
  41. void priv_deallocate(version_2)
  42. { m_alloc.deallocate_one(m_ptr); }
  43. BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator)
  44. public:
  45. pointer m_ptr;
  46. Allocator& m_alloc;
  47. scoped_deallocator(pointer p, Allocator& a)
  48. : m_ptr(p), m_alloc(a)
  49. {}
  50. ~scoped_deallocator()
  51. { if (m_ptr)priv_deallocate(alloc_version()); }
  52. scoped_deallocator(BOOST_RV_REF(scoped_deallocator) o)
  53. : m_ptr(o.m_ptr), m_alloc(o.m_alloc)
  54. { o.release(); }
  55. pointer get() const
  56. { return m_ptr; }
  57. void set(const pointer &p)
  58. { m_ptr = p; }
  59. void release()
  60. { m_ptr = 0; }
  61. };
  62. template <class Allocator>
  63. struct null_scoped_deallocator
  64. {
  65. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  66. typedef typename AllocTraits::pointer pointer;
  67. typedef typename AllocTraits::size_type size_type;
  68. null_scoped_deallocator(pointer, Allocator&, size_type)
  69. {}
  70. void release()
  71. {}
  72. pointer get() const
  73. { return pointer(); }
  74. void set(const pointer &)
  75. {}
  76. };
  77. //!A deleter for scoped_ptr that deallocates the memory
  78. //!allocated for an array of objects using a STL allocator.
  79. template <class Allocator>
  80. struct scoped_array_deallocator
  81. {
  82. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  83. typedef typename AllocTraits::pointer pointer;
  84. typedef typename AllocTraits::size_type size_type;
  85. scoped_array_deallocator(pointer p, Allocator& a, size_type length)
  86. : m_ptr(p), m_alloc(a), m_length(length) {}
  87. ~scoped_array_deallocator()
  88. { if (m_ptr) m_alloc.deallocate(m_ptr, m_length); }
  89. void release()
  90. { m_ptr = 0; }
  91. private:
  92. pointer m_ptr;
  93. Allocator& m_alloc;
  94. size_type m_length;
  95. };
  96. template <class Allocator>
  97. struct null_scoped_array_deallocator
  98. {
  99. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  100. typedef typename AllocTraits::pointer pointer;
  101. typedef typename AllocTraits::size_type size_type;
  102. null_scoped_array_deallocator(pointer, Allocator&, size_type)
  103. {}
  104. void release()
  105. {}
  106. };
  107. template <class Allocator>
  108. struct scoped_destroy_deallocator
  109. {
  110. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  111. typedef typename AllocTraits::pointer pointer;
  112. typedef typename AllocTraits::size_type size_type;
  113. typedef dtl::integral_constant<unsigned,
  114. boost::container::dtl::
  115. version<Allocator>::value> alloc_version;
  116. scoped_destroy_deallocator(pointer p, Allocator& a)
  117. : m_ptr(p), m_alloc(a) {}
  118. ~scoped_destroy_deallocator()
  119. {
  120. if(m_ptr){
  121. AllocTraits::destroy(m_alloc, boost::movelib::to_raw_pointer(m_ptr));
  122. priv_deallocate(m_ptr, alloc_version());
  123. }
  124. }
  125. void release()
  126. { m_ptr = 0; }
  127. private:
  128. void priv_deallocate(const pointer &p, version_1)
  129. { AllocTraits::deallocate(m_alloc, p, 1); }
  130. void priv_deallocate(const pointer &p, version_2)
  131. { m_alloc.deallocate_one(p); }
  132. pointer m_ptr;
  133. Allocator& m_alloc;
  134. };
  135. //!A deleter for scoped_ptr that destroys
  136. //!an object using a STL allocator.
  137. template <class Allocator>
  138. struct scoped_destructor_n
  139. {
  140. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  141. typedef typename AllocTraits::pointer pointer;
  142. typedef typename AllocTraits::value_type value_type;
  143. typedef typename AllocTraits::size_type size_type;
  144. scoped_destructor_n(pointer p, Allocator& a, size_type n)
  145. : m_p(p), m_a(a), m_n(n)
  146. {}
  147. void release()
  148. { m_p = 0; }
  149. void increment_size(size_type inc)
  150. { m_n += inc; }
  151. void increment_size_backwards(size_type inc)
  152. { m_n += inc; m_p -= inc; }
  153. void shrink_forward(size_type inc)
  154. { m_n -= inc; m_p += inc; }
  155. ~scoped_destructor_n()
  156. {
  157. if(!m_p) return;
  158. value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p);
  159. while(m_n--){
  160. AllocTraits::destroy(m_a, raw_ptr++);
  161. }
  162. }
  163. private:
  164. pointer m_p;
  165. Allocator & m_a;
  166. size_type m_n;
  167. };
  168. //!A deleter for scoped_ptr that destroys
  169. //!an object using a STL allocator.
  170. template <class Allocator>
  171. struct null_scoped_destructor_n
  172. {
  173. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  174. typedef typename AllocTraits::pointer pointer;
  175. typedef typename AllocTraits::size_type size_type;
  176. null_scoped_destructor_n(pointer, Allocator&, size_type)
  177. {}
  178. void increment_size(size_type)
  179. {}
  180. void increment_size_backwards(size_type)
  181. {}
  182. void shrink_forward(size_type)
  183. {}
  184. void release()
  185. {}
  186. };
  187. template<class Allocator>
  188. class scoped_destructor
  189. {
  190. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  191. public:
  192. typedef typename Allocator::value_type value_type;
  193. scoped_destructor(Allocator &a, value_type *pv)
  194. : pv_(pv), a_(a)
  195. {}
  196. ~scoped_destructor()
  197. {
  198. if(pv_){
  199. AllocTraits::destroy(a_, pv_);
  200. }
  201. }
  202. void release()
  203. { pv_ = 0; }
  204. void set(value_type *ptr) { pv_ = ptr; }
  205. value_type *get() const { return pv_; }
  206. private:
  207. value_type *pv_;
  208. Allocator &a_;
  209. };
  210. template<class Allocator, class Value = typename Allocator::value_type>
  211. class value_destructor
  212. {
  213. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  214. public:
  215. typedef Value value_type;
  216. value_destructor(Allocator &a, value_type &rv)
  217. : rv_(rv), a_(a)
  218. {}
  219. ~value_destructor()
  220. {
  221. AllocTraits::destroy(a_, &rv_);
  222. }
  223. private:
  224. value_type &rv_;
  225. Allocator &a_;
  226. };
  227. template <class Allocator>
  228. class allocator_destroyer
  229. {
  230. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  231. typedef typename AllocTraits::value_type value_type;
  232. typedef typename AllocTraits::pointer pointer;
  233. typedef dtl::integral_constant<unsigned,
  234. boost::container::dtl::
  235. version<Allocator>::value> alloc_version;
  236. private:
  237. Allocator & a_;
  238. private:
  239. void priv_deallocate(const pointer &p, version_1)
  240. { AllocTraits::deallocate(a_,p, 1); }
  241. void priv_deallocate(const pointer &p, version_2)
  242. { a_.deallocate_one(p); }
  243. public:
  244. explicit allocator_destroyer(Allocator &a)
  245. : a_(a)
  246. {}
  247. void operator()(const pointer &p)
  248. {
  249. AllocTraits::destroy(a_, boost::movelib::to_raw_pointer(p));
  250. this->priv_deallocate(p, alloc_version());
  251. }
  252. };
  253. template <class Allocator>
  254. class allocator_destroyer_and_chain_builder
  255. {
  256. typedef allocator_traits<Allocator> allocator_traits_type;
  257. typedef typename allocator_traits_type::value_type value_type;
  258. typedef typename Allocator::multiallocation_chain multiallocation_chain;
  259. Allocator & a_;
  260. multiallocation_chain &c_;
  261. public:
  262. allocator_destroyer_and_chain_builder(Allocator &a, multiallocation_chain &c)
  263. : a_(a), c_(c)
  264. {}
  265. void operator()(const typename Allocator::pointer &p)
  266. {
  267. allocator_traits<Allocator>::destroy(a_, boost::movelib::to_raw_pointer(p));
  268. c_.push_back(p);
  269. }
  270. };
  271. template <class Allocator>
  272. class allocator_multialloc_chain_node_deallocator
  273. {
  274. typedef allocator_traits<Allocator> allocator_traits_type;
  275. typedef typename allocator_traits_type::value_type value_type;
  276. typedef typename Allocator::multiallocation_chain multiallocation_chain;
  277. typedef allocator_destroyer_and_chain_builder<Allocator> chain_builder;
  278. Allocator & a_;
  279. multiallocation_chain c_;
  280. public:
  281. allocator_multialloc_chain_node_deallocator(Allocator &a)
  282. : a_(a), c_()
  283. {}
  284. chain_builder get_chain_builder()
  285. { return chain_builder(a_, c_); }
  286. ~allocator_multialloc_chain_node_deallocator()
  287. {
  288. a_.deallocate_individual(c_);
  289. }
  290. };
  291. } //namespace dtl {
  292. } //namespace container {
  293. } //namespace boost {
  294. #include <boost/container/detail/config_end.hpp>
  295. #endif //#ifndef BOOST_CONTAINER_DESTROYERS_HPP