destroyers.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  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. #include <boost/move/detail/iterator_to_raw_pointer.hpp>
  26. namespace boost {
  27. namespace container {
  28. namespace dtl {
  29. //!A deleter for scoped_ptr that deallocates the memory
  30. //!allocated for an object using a STL allocator.
  31. template <class Allocator>
  32. struct scoped_deallocator
  33. {
  34. typedef allocator_traits<Allocator> allocator_traits_type;
  35. typedef typename allocator_traits_type::pointer pointer;
  36. typedef dtl::integral_constant<unsigned,
  37. boost::container::dtl::
  38. version<Allocator>::value> alloc_version;
  39. private:
  40. void priv_deallocate(version_1)
  41. { m_alloc.deallocate(m_ptr, 1); }
  42. void priv_deallocate(version_2)
  43. { m_alloc.deallocate_one(m_ptr); }
  44. BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator)
  45. public:
  46. pointer m_ptr;
  47. Allocator& m_alloc;
  48. scoped_deallocator(pointer p, Allocator& a)
  49. : m_ptr(p), m_alloc(a)
  50. {}
  51. ~scoped_deallocator()
  52. { if (m_ptr)priv_deallocate(alloc_version()); }
  53. scoped_deallocator(BOOST_RV_REF(scoped_deallocator) o)
  54. : m_ptr(o.m_ptr), m_alloc(o.m_alloc)
  55. { o.release(); }
  56. pointer get() const
  57. { return m_ptr; }
  58. void set(const pointer &p)
  59. { m_ptr = p; }
  60. void release()
  61. { m_ptr = 0; }
  62. };
  63. template <class Allocator>
  64. struct null_scoped_deallocator
  65. {
  66. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  67. typedef typename AllocTraits::pointer pointer;
  68. null_scoped_deallocator(pointer, Allocator&, std::size_t)
  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, std::size_t length)
  86. : m_ptr(p), m_alloc(a), m_length(length) {}
  87. ~scoped_array_deallocator()
  88. { if (m_ptr) m_alloc.deallocate(m_ptr, size_type(m_length)); }
  89. void release()
  90. { m_ptr = 0; }
  91. private:
  92. pointer m_ptr;
  93. Allocator& m_alloc;
  94. std::size_t 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. null_scoped_array_deallocator(pointer, Allocator&, std::size_t)
  102. {}
  103. void release()
  104. {}
  105. };
  106. template <class Allocator>
  107. struct scoped_node_destroy_deallocator
  108. {
  109. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  110. typedef typename AllocTraits::pointer pointer;
  111. typedef dtl::integral_constant<unsigned,
  112. boost::container::dtl::
  113. version<Allocator>::value> alloc_version;
  114. scoped_node_destroy_deallocator(pointer p, Allocator& a)
  115. : m_ptr(p), m_alloc(a) {}
  116. ~scoped_node_destroy_deallocator()
  117. {
  118. if(m_ptr){
  119. boost::movelib::to_raw_pointer(m_ptr)->destructor(m_alloc);
  120. priv_deallocate(m_ptr, alloc_version());
  121. }
  122. }
  123. void release()
  124. { m_ptr = 0; }
  125. private:
  126. void priv_deallocate(const pointer &p, version_1)
  127. { AllocTraits::deallocate(m_alloc, p, 1); }
  128. void priv_deallocate(const pointer &p, version_2)
  129. { m_alloc.deallocate_one(p); }
  130. pointer m_ptr;
  131. Allocator& m_alloc;
  132. };
  133. //!A deleter for scoped_ptr that destroys
  134. //!an object using a STL allocator.
  135. template <class Allocator, class Ptr = typename allocator_traits<Allocator>::pointer>
  136. struct scoped_destructor_n
  137. {
  138. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  139. typedef Ptr pointer;
  140. typedef typename AllocTraits::value_type value_type;
  141. inline scoped_destructor_n(Ptr p, Allocator& a, std::size_t n)
  142. : m_p(p), m_n(n), m_a(a)
  143. {}
  144. inline void release()
  145. { m_p = Ptr(); m_n = 0; }
  146. inline void increment_size(std::size_t inc)
  147. { m_n += inc; }
  148. inline void increment_size_backwards(std::size_t inc)
  149. { m_n += inc; m_p -= std::ptrdiff_t(inc); }
  150. inline void shrink_forward(std::size_t inc)
  151. { m_n -= inc; m_p += std::ptrdiff_t(inc); }
  152. inline void set_size(std::size_t sz)
  153. { m_n = sz; }
  154. ~scoped_destructor_n()
  155. {
  156. if(m_n){
  157. value_type *raw_ptr = boost::movelib::iterator_to_raw_pointer(m_p);
  158. do {
  159. --m_n;
  160. AllocTraits::destroy(m_a, raw_ptr);
  161. ++raw_ptr;
  162. } while(m_n);
  163. }
  164. }
  165. private:
  166. pointer m_p;
  167. std::size_t m_n;
  168. Allocator& m_a;
  169. };
  170. //!A deleter for scoped_ptr that destroys
  171. //!an object using a STL allocator.
  172. template <class Allocator, class Ptr = typename allocator_traits<Allocator>::pointer>
  173. struct null_scoped_destructor_n
  174. {
  175. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  176. typedef Ptr pointer;
  177. inline null_scoped_destructor_n(Ptr, Allocator&, std::size_t)
  178. {}
  179. inline void increment_size(std::size_t)
  180. {}
  181. inline void increment_size_backwards(std::size_t)
  182. {}
  183. inline void set_size(std::size_t )
  184. {}
  185. inline void shrink_forward(std::size_t)
  186. {}
  187. inline 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. inline scoped_destructor_range(pointer p, pointer e, Allocator& a)
  199. : m_p(p), m_e(e), m_a(a)
  200. {}
  201. inline void release()
  202. { m_p = pointer(); m_e = pointer(); }
  203. inline void set_end(pointer e)
  204. { m_e = e; }
  205. inline void set_begin(pointer b)
  206. { m_p = b; }
  207. inline 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. inline null_scoped_destructor_range(pointer, pointer, Allocator&)
  230. {}
  231. inline void release()
  232. {}
  233. inline void set_end(pointer)
  234. {}
  235. inline void set_begin(pointer)
  236. {}
  237. inline 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. inline scoped_destructor(Allocator &a, value_type *pv)
  247. : pv_(pv), a_(a)
  248. {}
  249. inline ~scoped_destructor()
  250. {
  251. if(pv_){
  252. AllocTraits::destroy(a_, pv_);
  253. }
  254. }
  255. inline void release()
  256. { pv_ = 0; }
  257. inline void set(value_type *ptr) { pv_ = ptr; }
  258. inline value_type *get() const { return pv_; }
  259. private:
  260. value_type *pv_;
  261. Allocator &a_;
  262. };
  263. template<class Allocator>
  264. class null_scoped_destructor
  265. {
  266. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  267. public:
  268. typedef typename Allocator::value_type value_type;
  269. inline null_scoped_destructor(Allocator &, value_type *)
  270. {}
  271. inline ~null_scoped_destructor()
  272. {}
  273. inline void release()
  274. {}
  275. inline void set(value_type *) { }
  276. inline value_type *get() const { return 0; }
  277. };
  278. template<class Allocator, class Value = typename Allocator::value_type>
  279. class value_destructor
  280. {
  281. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  282. public:
  283. typedef Value value_type;
  284. inline value_destructor(Allocator &a, value_type &rv)
  285. : rv_(rv), a_(a)
  286. {}
  287. inline ~value_destructor()
  288. {
  289. AllocTraits::destroy(a_, &rv_);
  290. }
  291. private:
  292. value_type &rv_;
  293. Allocator &a_;
  294. };
  295. template <class Allocator>
  296. class allocator_node_destroyer
  297. {
  298. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  299. typedef typename AllocTraits::value_type value_type;
  300. typedef typename AllocTraits::pointer pointer;
  301. typedef dtl::integral_constant<unsigned,
  302. boost::container::dtl::
  303. version<Allocator>::value> alloc_version;
  304. private:
  305. Allocator & a_;
  306. private:
  307. inline void priv_deallocate(const pointer &p, version_1)
  308. { AllocTraits::deallocate(a_,p, 1); }
  309. inline void priv_deallocate(const pointer &p, version_2)
  310. { a_.deallocate_one(p); }
  311. public:
  312. inline explicit allocator_node_destroyer(Allocator &a)
  313. : a_(a)
  314. {}
  315. inline void operator()(const pointer &p)
  316. {
  317. boost::movelib::to_raw_pointer(p)->destructor(a_);
  318. this->priv_deallocate(p, alloc_version());
  319. }
  320. };
  321. template<class Allocator>
  322. class scoped_node_destructor
  323. {
  324. typedef boost::container::allocator_traits<Allocator> AllocTraits;
  325. public:
  326. typedef typename Allocator::value_type value_type;
  327. inline scoped_node_destructor(Allocator &a, value_type *pv)
  328. : pv_(pv), a_(a)
  329. {}
  330. inline ~scoped_node_destructor()
  331. {
  332. if(pv_){
  333. pv_->destructor(a_);
  334. }
  335. }
  336. inline void release()
  337. { pv_ = 0; }
  338. inline void set(value_type *ptr) { pv_ = ptr; }
  339. inline value_type *get() const { return pv_; }
  340. private:
  341. value_type *pv_;
  342. Allocator &a_;
  343. };
  344. template <class Allocator>
  345. class allocator_node_destroyer_and_chain_builder
  346. {
  347. typedef allocator_traits<Allocator> allocator_traits_type;
  348. typedef typename allocator_traits_type::value_type value_type;
  349. typedef typename Allocator::multiallocation_chain multiallocation_chain;
  350. Allocator & a_;
  351. multiallocation_chain &c_;
  352. public:
  353. inline allocator_node_destroyer_and_chain_builder(Allocator &a, multiallocation_chain &c)
  354. : a_(a), c_(c)
  355. {}
  356. inline void operator()(const typename Allocator::pointer &p)
  357. {
  358. boost::movelib::to_raw_pointer(p)->destructor(a_);
  359. c_.push_back(p);
  360. }
  361. };
  362. template <class Allocator>
  363. class allocator_multialloc_chain_node_deallocator
  364. {
  365. typedef allocator_traits<Allocator> allocator_traits_type;
  366. typedef typename allocator_traits_type::value_type value_type;
  367. typedef typename Allocator::multiallocation_chain multiallocation_chain;
  368. typedef allocator_node_destroyer_and_chain_builder<Allocator> chain_builder;
  369. Allocator & a_;
  370. multiallocation_chain c_;
  371. public:
  372. inline allocator_multialloc_chain_node_deallocator(Allocator &a)
  373. : a_(a), c_()
  374. {}
  375. inline chain_builder get_chain_builder()
  376. { return chain_builder(a_, c_); }
  377. inline ~allocator_multialloc_chain_node_deallocator()
  378. {
  379. a_.deallocate_individual(c_);
  380. }
  381. };
  382. } //namespace dtl {
  383. } //namespace container {
  384. } //namespace boost {
  385. #include <boost/container/detail/config_end.hpp>
  386. #endif //#ifndef BOOST_CONTAINER_DESTROYERS_HPP