destroyers.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  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. null_scoped_deallocator(pointer, Allocator&, std::size_t)
  68. {}
  69. void release()
  70. {}
  71. pointer get() const
  72. { return pointer(); }
  73. void set(const pointer &)
  74. {}
  75. };
  76. //!A deleter for scoped_ptr that deallocates the memory
  77. //!allocated for an array of objects using a STL allocator.
  78. template <class Allocator>
  79. struct scoped_array_deallocator
  80. {
  81. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  82. typedef typename AllocTraits::pointer pointer;
  83. typedef typename AllocTraits::size_type size_type;
  84. scoped_array_deallocator(pointer p, Allocator& a, std::size_t length)
  85. : m_ptr(p), m_alloc(a), m_length(length) {}
  86. ~scoped_array_deallocator()
  87. { if (m_ptr) m_alloc.deallocate(m_ptr, size_type(m_length)); }
  88. void release()
  89. { m_ptr = 0; }
  90. private:
  91. pointer m_ptr;
  92. Allocator& m_alloc;
  93. std::size_t m_length;
  94. };
  95. template <class Allocator>
  96. struct null_scoped_array_deallocator
  97. {
  98. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  99. typedef typename AllocTraits::pointer pointer;
  100. null_scoped_array_deallocator(pointer, Allocator&, std::size_t)
  101. {}
  102. void release()
  103. {}
  104. };
  105. template <class Allocator>
  106. struct scoped_node_destroy_deallocator
  107. {
  108. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  109. typedef typename AllocTraits::pointer pointer;
  110. typedef dtl::integral_constant<unsigned,
  111. boost::container::dtl::
  112. version<Allocator>::value> alloc_version;
  113. scoped_node_destroy_deallocator(pointer p, Allocator& a)
  114. : m_ptr(p), m_alloc(a) {}
  115. ~scoped_node_destroy_deallocator()
  116. {
  117. if(m_ptr){
  118. boost::movelib::to_raw_pointer(m_ptr)->destructor(m_alloc);
  119. priv_deallocate(m_ptr, alloc_version());
  120. }
  121. }
  122. void release()
  123. { m_ptr = 0; }
  124. private:
  125. void priv_deallocate(const pointer &p, version_1)
  126. { AllocTraits::deallocate(m_alloc, p, 1); }
  127. void priv_deallocate(const pointer &p, version_2)
  128. { m_alloc.deallocate_one(p); }
  129. pointer m_ptr;
  130. Allocator& m_alloc;
  131. };
  132. //!A deleter for scoped_ptr that destroys
  133. //!an object using a STL allocator.
  134. template <class Allocator>
  135. struct scoped_destructor_n
  136. {
  137. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  138. typedef typename AllocTraits::pointer pointer;
  139. typedef typename AllocTraits::value_type value_type;
  140. BOOST_CONTAINER_FORCEINLINE scoped_destructor_n(pointer p, Allocator& a, std::size_t n)
  141. : m_p(p), m_a(a), m_n(n)
  142. {}
  143. BOOST_CONTAINER_FORCEINLINE void release()
  144. { m_p = 0; m_n = 0; }
  145. BOOST_CONTAINER_FORCEINLINE void increment_size(std::size_t inc)
  146. { m_n += inc; }
  147. BOOST_CONTAINER_FORCEINLINE void increment_size_backwards(std::size_t inc)
  148. { m_n += inc; m_p -= std::ptrdiff_t(inc); }
  149. BOOST_CONTAINER_FORCEINLINE void shrink_forward(std::size_t inc)
  150. { m_n -= inc; m_p += std::ptrdiff_t(inc); }
  151. ~scoped_destructor_n()
  152. {
  153. if(m_n){
  154. value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p);
  155. do {
  156. --m_n;
  157. AllocTraits::destroy(m_a, raw_ptr);
  158. ++raw_ptr;
  159. } while(m_n);
  160. }
  161. }
  162. private:
  163. pointer m_p;
  164. Allocator & m_a;
  165. std::size_t m_n;
  166. };
  167. //!A deleter for scoped_ptr that destroys
  168. //!an object using a STL allocator.
  169. template <class Allocator>
  170. struct null_scoped_destructor_n
  171. {
  172. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  173. typedef typename AllocTraits::pointer pointer;
  174. BOOST_CONTAINER_FORCEINLINE null_scoped_destructor_n(pointer, Allocator&, std::size_t)
  175. {}
  176. BOOST_CONTAINER_FORCEINLINE void increment_size(std::size_t)
  177. {}
  178. BOOST_CONTAINER_FORCEINLINE void increment_size_backwards(std::size_t)
  179. {}
  180. BOOST_CONTAINER_FORCEINLINE void shrink_forward(std::size_t)
  181. {}
  182. BOOST_CONTAINER_FORCEINLINE void release()
  183. {}
  184. };
  185. //!A deleter for scoped_ptr that destroys
  186. //!an object using a STL allocator.
  187. template <class Allocator>
  188. struct scoped_destructor_range
  189. {
  190. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  191. typedef typename AllocTraits::pointer pointer;
  192. typedef typename AllocTraits::value_type value_type;
  193. BOOST_CONTAINER_FORCEINLINE scoped_destructor_range(pointer p, pointer e, Allocator& a)
  194. : m_p(p), m_e(e), m_a(a)
  195. {}
  196. BOOST_CONTAINER_FORCEINLINE void release()
  197. { m_p = pointer(); m_e = pointer(); }
  198. BOOST_CONTAINER_FORCEINLINE void set_end(pointer e)
  199. { m_e = e; }
  200. BOOST_CONTAINER_FORCEINLINE void set_begin(pointer b)
  201. { m_p = b; }
  202. BOOST_CONTAINER_FORCEINLINE void set_range(pointer b, pointer e)
  203. { m_p = b; m_e = e; }
  204. ~scoped_destructor_range()
  205. {
  206. while(m_p != m_e){
  207. value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p);
  208. AllocTraits::destroy(m_a, raw_ptr);
  209. ++m_p;
  210. }
  211. }
  212. private:
  213. pointer m_p;
  214. pointer m_e;
  215. Allocator & m_a;
  216. };
  217. //!A deleter for scoped_ptr that destroys
  218. //!an object using a STL allocator.
  219. template <class Allocator>
  220. struct null_scoped_destructor_range
  221. {
  222. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  223. typedef typename AllocTraits::pointer pointer;
  224. BOOST_CONTAINER_FORCEINLINE null_scoped_destructor_range(pointer, pointer, Allocator&)
  225. {}
  226. BOOST_CONTAINER_FORCEINLINE void release()
  227. {}
  228. BOOST_CONTAINER_FORCEINLINE void set_end(pointer)
  229. {}
  230. BOOST_CONTAINER_FORCEINLINE void set_begin(pointer)
  231. {}
  232. BOOST_CONTAINER_FORCEINLINE void set_range(pointer, pointer)
  233. {}
  234. };
  235. template<class Allocator>
  236. class scoped_destructor
  237. {
  238. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  239. public:
  240. typedef typename Allocator::value_type value_type;
  241. BOOST_CONTAINER_FORCEINLINE scoped_destructor(Allocator &a, value_type *pv)
  242. : pv_(pv), a_(a)
  243. {}
  244. BOOST_CONTAINER_FORCEINLINE ~scoped_destructor()
  245. {
  246. if(pv_){
  247. AllocTraits::destroy(a_, pv_);
  248. }
  249. }
  250. BOOST_CONTAINER_FORCEINLINE void release()
  251. { pv_ = 0; }
  252. BOOST_CONTAINER_FORCEINLINE void set(value_type *ptr) { pv_ = ptr; }
  253. BOOST_CONTAINER_FORCEINLINE value_type *get() const { return pv_; }
  254. private:
  255. value_type *pv_;
  256. Allocator &a_;
  257. };
  258. template<class Allocator, class Value = typename Allocator::value_type>
  259. class value_destructor
  260. {
  261. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  262. public:
  263. typedef Value value_type;
  264. BOOST_CONTAINER_FORCEINLINE value_destructor(Allocator &a, value_type &rv)
  265. : rv_(rv), a_(a)
  266. {}
  267. BOOST_CONTAINER_FORCEINLINE ~value_destructor()
  268. {
  269. AllocTraits::destroy(a_, &rv_);
  270. }
  271. private:
  272. value_type &rv_;
  273. Allocator &a_;
  274. };
  275. template <class Allocator>
  276. class allocator_node_destroyer
  277. {
  278. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  279. typedef typename AllocTraits::value_type value_type;
  280. typedef typename AllocTraits::pointer pointer;
  281. typedef dtl::integral_constant<unsigned,
  282. boost::container::dtl::
  283. version<Allocator>::value> alloc_version;
  284. private:
  285. Allocator & a_;
  286. private:
  287. BOOST_CONTAINER_FORCEINLINE void priv_deallocate(const pointer &p, version_1)
  288. { AllocTraits::deallocate(a_,p, 1); }
  289. BOOST_CONTAINER_FORCEINLINE void priv_deallocate(const pointer &p, version_2)
  290. { a_.deallocate_one(p); }
  291. public:
  292. BOOST_CONTAINER_FORCEINLINE explicit allocator_node_destroyer(Allocator &a)
  293. : a_(a)
  294. {}
  295. BOOST_CONTAINER_FORCEINLINE void operator()(const pointer &p)
  296. {
  297. boost::movelib::to_raw_pointer(p)->destructor(a_);
  298. this->priv_deallocate(p, alloc_version());
  299. }
  300. };
  301. template<class Allocator>
  302. class scoped_node_destructor
  303. {
  304. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  305. public:
  306. typedef typename Allocator::value_type value_type;
  307. BOOST_CONTAINER_FORCEINLINE scoped_node_destructor(Allocator &a, value_type *pv)
  308. : pv_(pv), a_(a)
  309. {}
  310. BOOST_CONTAINER_FORCEINLINE ~scoped_node_destructor()
  311. {
  312. if(pv_){
  313. pv_->destructor(a_);
  314. }
  315. }
  316. BOOST_CONTAINER_FORCEINLINE void release()
  317. { pv_ = 0; }
  318. BOOST_CONTAINER_FORCEINLINE void set(value_type *ptr) { pv_ = ptr; }
  319. BOOST_CONTAINER_FORCEINLINE value_type *get() const { return pv_; }
  320. private:
  321. value_type *pv_;
  322. Allocator &a_;
  323. };
  324. template <class Allocator>
  325. class allocator_node_destroyer_and_chain_builder
  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. Allocator & a_;
  331. multiallocation_chain &c_;
  332. public:
  333. BOOST_CONTAINER_FORCEINLINE allocator_node_destroyer_and_chain_builder(Allocator &a, multiallocation_chain &c)
  334. : a_(a), c_(c)
  335. {}
  336. BOOST_CONTAINER_FORCEINLINE void operator()(const typename Allocator::pointer &p)
  337. {
  338. boost::movelib::to_raw_pointer(p)->destructor(a_);
  339. c_.push_back(p);
  340. }
  341. };
  342. template <class Allocator>
  343. class allocator_multialloc_chain_node_deallocator
  344. {
  345. typedef allocator_traits<Allocator> allocator_traits_type;
  346. typedef typename allocator_traits_type::value_type value_type;
  347. typedef typename Allocator::multiallocation_chain multiallocation_chain;
  348. typedef allocator_node_destroyer_and_chain_builder<Allocator> chain_builder;
  349. Allocator & a_;
  350. multiallocation_chain c_;
  351. public:
  352. BOOST_CONTAINER_FORCEINLINE allocator_multialloc_chain_node_deallocator(Allocator &a)
  353. : a_(a), c_()
  354. {}
  355. BOOST_CONTAINER_FORCEINLINE chain_builder get_chain_builder()
  356. { return chain_builder(a_, c_); }
  357. BOOST_CONTAINER_FORCEINLINE ~allocator_multialloc_chain_node_deallocator()
  358. {
  359. a_.deallocate_individual(c_);
  360. }
  361. };
  362. } //namespace dtl {
  363. } //namespace container {
  364. } //namespace boost {
  365. #include <boost/container/detail/config_end.hpp>
  366. #endif //#ifndef BOOST_CONTAINER_DESTROYERS_HPP