destroyers.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  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. BOOST_CONTAINER_FORCEINLINE scoped_destructor_n(pointer p, Allocator& a, size_type n)
  145. : m_p(p), m_a(a), m_n(n)
  146. {}
  147. BOOST_CONTAINER_FORCEINLINE void release()
  148. { m_p = 0; m_n = 0; }
  149. BOOST_CONTAINER_FORCEINLINE void increment_size(size_type inc)
  150. { m_n += inc; }
  151. BOOST_CONTAINER_FORCEINLINE void increment_size_backwards(size_type inc)
  152. { m_n += inc; m_p -= inc; }
  153. BOOST_CONTAINER_FORCEINLINE void shrink_forward(size_type inc)
  154. { m_n -= inc; m_p += inc; }
  155. ~scoped_destructor_n()
  156. {
  157. if(m_n){
  158. value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p);
  159. do {
  160. --m_n;
  161. AllocTraits::destroy(m_a, raw_ptr);
  162. ++raw_ptr;
  163. } while(m_n);
  164. }
  165. }
  166. private:
  167. pointer m_p;
  168. Allocator & m_a;
  169. size_type m_n;
  170. };
  171. //!A deleter for scoped_ptr that destroys
  172. //!an object using a STL allocator.
  173. template <class Allocator>
  174. struct null_scoped_destructor_n
  175. {
  176. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  177. typedef typename AllocTraits::pointer pointer;
  178. typedef typename AllocTraits::size_type size_type;
  179. BOOST_CONTAINER_FORCEINLINE null_scoped_destructor_n(pointer, Allocator&, size_type)
  180. {}
  181. BOOST_CONTAINER_FORCEINLINE void increment_size(size_type)
  182. {}
  183. BOOST_CONTAINER_FORCEINLINE void increment_size_backwards(size_type)
  184. {}
  185. BOOST_CONTAINER_FORCEINLINE void shrink_forward(size_type)
  186. {}
  187. BOOST_CONTAINER_FORCEINLINE void release()
  188. {}
  189. };
  190. //!A deleter for scoped_ptr that destroys
  191. //!an object using a STL allocator.
  192. template <class Allocator>
  193. struct scoped_destructor_range
  194. {
  195. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  196. typedef typename AllocTraits::pointer pointer;
  197. typedef typename AllocTraits::value_type value_type;
  198. BOOST_CONTAINER_FORCEINLINE scoped_destructor_range(pointer p, pointer e, Allocator& a)
  199. : m_p(p), m_e(e), m_a(a)
  200. {}
  201. BOOST_CONTAINER_FORCEINLINE void release()
  202. { m_p = pointer(); m_e = pointer(); }
  203. BOOST_CONTAINER_FORCEINLINE void set_end(pointer e)
  204. { m_e = e; }
  205. BOOST_CONTAINER_FORCEINLINE void set_begin(pointer b)
  206. { m_p = b; }
  207. BOOST_CONTAINER_FORCEINLINE void set_range(pointer b, pointer e)
  208. { m_p = b; m_e = e; }
  209. ~scoped_destructor_range()
  210. {
  211. while(m_p != m_e){
  212. value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p);
  213. AllocTraits::destroy(m_a, raw_ptr);
  214. ++m_p;
  215. }
  216. }
  217. private:
  218. pointer m_p;
  219. pointer m_e;
  220. Allocator & m_a;
  221. };
  222. //!A deleter for scoped_ptr that destroys
  223. //!an object using a STL allocator.
  224. template <class Allocator>
  225. struct null_scoped_destructor_range
  226. {
  227. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  228. typedef typename AllocTraits::pointer pointer;
  229. BOOST_CONTAINER_FORCEINLINE null_scoped_destructor_range(pointer, pointer, Allocator&)
  230. {}
  231. BOOST_CONTAINER_FORCEINLINE void release()
  232. {}
  233. BOOST_CONTAINER_FORCEINLINE void set_end(pointer)
  234. {}
  235. BOOST_CONTAINER_FORCEINLINE void set_begin(pointer)
  236. {}
  237. BOOST_CONTAINER_FORCEINLINE void set_range(pointer, pointer)
  238. {}
  239. };
  240. template<class Allocator>
  241. class scoped_destructor
  242. {
  243. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  244. public:
  245. typedef typename Allocator::value_type value_type;
  246. BOOST_CONTAINER_FORCEINLINE scoped_destructor(Allocator &a, value_type *pv)
  247. : pv_(pv), a_(a)
  248. {}
  249. BOOST_CONTAINER_FORCEINLINE ~scoped_destructor()
  250. {
  251. if(pv_){
  252. AllocTraits::destroy(a_, pv_);
  253. }
  254. }
  255. BOOST_CONTAINER_FORCEINLINE void release()
  256. { pv_ = 0; }
  257. BOOST_CONTAINER_FORCEINLINE void set(value_type *ptr) { pv_ = ptr; }
  258. BOOST_CONTAINER_FORCEINLINE value_type *get() const { return pv_; }
  259. private:
  260. value_type *pv_;
  261. Allocator &a_;
  262. };
  263. template<class Allocator, class Value = typename Allocator::value_type>
  264. class value_destructor
  265. {
  266. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  267. public:
  268. typedef Value value_type;
  269. BOOST_CONTAINER_FORCEINLINE value_destructor(Allocator &a, value_type &rv)
  270. : rv_(rv), a_(a)
  271. {}
  272. BOOST_CONTAINER_FORCEINLINE ~value_destructor()
  273. {
  274. AllocTraits::destroy(a_, &rv_);
  275. }
  276. private:
  277. value_type &rv_;
  278. Allocator &a_;
  279. };
  280. template <class Allocator>
  281. class allocator_destroyer
  282. {
  283. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  284. typedef typename AllocTraits::value_type value_type;
  285. typedef typename AllocTraits::pointer pointer;
  286. typedef dtl::integral_constant<unsigned,
  287. boost::container::dtl::
  288. version<Allocator>::value> alloc_version;
  289. private:
  290. Allocator & a_;
  291. private:
  292. BOOST_CONTAINER_FORCEINLINE void priv_deallocate(const pointer &p, version_1)
  293. { AllocTraits::deallocate(a_,p, 1); }
  294. BOOST_CONTAINER_FORCEINLINE void priv_deallocate(const pointer &p, version_2)
  295. { a_.deallocate_one(p); }
  296. public:
  297. BOOST_CONTAINER_FORCEINLINE explicit allocator_destroyer(Allocator &a)
  298. : a_(a)
  299. {}
  300. BOOST_CONTAINER_FORCEINLINE void operator()(const pointer &p)
  301. {
  302. AllocTraits::destroy(a_, boost::movelib::to_raw_pointer(p));
  303. this->priv_deallocate(p, alloc_version());
  304. }
  305. };
  306. template <class Allocator>
  307. class allocator_destroyer_and_chain_builder
  308. {
  309. typedef allocator_traits<Allocator> allocator_traits_type;
  310. typedef typename allocator_traits_type::value_type value_type;
  311. typedef typename Allocator::multiallocation_chain multiallocation_chain;
  312. Allocator & a_;
  313. multiallocation_chain &c_;
  314. public:
  315. BOOST_CONTAINER_FORCEINLINE allocator_destroyer_and_chain_builder(Allocator &a, multiallocation_chain &c)
  316. : a_(a), c_(c)
  317. {}
  318. BOOST_CONTAINER_FORCEINLINE void operator()(const typename Allocator::pointer &p)
  319. {
  320. allocator_traits<Allocator>::destroy(a_, boost::movelib::to_raw_pointer(p));
  321. c_.push_back(p);
  322. }
  323. };
  324. template <class Allocator>
  325. class allocator_multialloc_chain_node_deallocator
  326. {
  327. typedef allocator_traits<Allocator> allocator_traits_type;
  328. typedef typename allocator_traits_type::value_type value_type;
  329. typedef typename Allocator::multiallocation_chain multiallocation_chain;
  330. typedef allocator_destroyer_and_chain_builder<Allocator> chain_builder;
  331. Allocator & a_;
  332. multiallocation_chain c_;
  333. public:
  334. BOOST_CONTAINER_FORCEINLINE allocator_multialloc_chain_node_deallocator(Allocator &a)
  335. : a_(a), c_()
  336. {}
  337. BOOST_CONTAINER_FORCEINLINE chain_builder get_chain_builder()
  338. { return chain_builder(a_, c_); }
  339. BOOST_CONTAINER_FORCEINLINE ~allocator_multialloc_chain_node_deallocator()
  340. {
  341. a_.deallocate_individual(c_);
  342. }
  343. };
  344. } //namespace dtl {
  345. } //namespace container {
  346. } //namespace boost {
  347. #include <boost/container/detail/config_end.hpp>
  348. #endif //#ifndef BOOST_CONTAINER_DESTROYERS_HPP