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 13 #ifndef BOOST_CONTAINER_DESTROYERS_HPP 14 #define BOOST_CONTAINER_DESTROYERS_HPP 15 16 #ifndef BOOST_CONFIG_HPP 17 # include <boost/config.hpp> 18 #endif 19 20 #if defined(BOOST_HAS_PRAGMA_ONCE) 21 # pragma once 22 #endif 23 24 #include <boost/container/detail/config_begin.hpp> 25 #include <boost/container/detail/workaround.hpp> 26 27 #include <boost/container/allocator_traits.hpp> 28 #include <boost/move/detail/to_raw_pointer.hpp> 29 #include <boost/container/detail/version_type.hpp> 30 31 namespace boost { 32 namespace container { 33 namespace dtl { 34 35 //!A deleter for scoped_ptr that deallocates the memory 36 //!allocated for an object using a STL allocator. 37 template <class Allocator> 38 struct scoped_deallocator 39 { 40 typedef allocator_traits<Allocator> allocator_traits_type; 41 typedef typename allocator_traits_type::pointer pointer; 42 typedef dtl::integral_constant<unsigned, 43 boost::container::dtl:: 44 version<Allocator>::value> alloc_version; 45 46 private: priv_deallocateboost::container::dtl::scoped_deallocator47 void priv_deallocate(version_1) 48 { m_alloc.deallocate(m_ptr, 1); } 49 priv_deallocateboost::container::dtl::scoped_deallocator50 void priv_deallocate(version_2) 51 { m_alloc.deallocate_one(m_ptr); } 52 53 BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator) 54 55 public: 56 57 pointer m_ptr; 58 Allocator& m_alloc; 59 scoped_deallocatorboost::container::dtl::scoped_deallocator60 scoped_deallocator(pointer p, Allocator& a) 61 : m_ptr(p), m_alloc(a) 62 {} 63 ~scoped_deallocatorboost::container::dtl::scoped_deallocator64 ~scoped_deallocator() 65 { if (m_ptr)priv_deallocate(alloc_version()); } 66 scoped_deallocatorboost::container::dtl::scoped_deallocator67 scoped_deallocator(BOOST_RV_REF(scoped_deallocator) o) 68 : m_ptr(o.m_ptr), m_alloc(o.m_alloc) 69 { o.release(); } 70 getboost::container::dtl::scoped_deallocator71 pointer get() const 72 { return m_ptr; } 73 setboost::container::dtl::scoped_deallocator74 void set(const pointer &p) 75 { m_ptr = p; } 76 releaseboost::container::dtl::scoped_deallocator77 void release() 78 { m_ptr = 0; } 79 }; 80 81 template <class Allocator> 82 struct null_scoped_deallocator 83 { 84 typedef boost::container::allocator_traits<Allocator> AllocTraits; 85 typedef typename AllocTraits::pointer pointer; 86 null_scoped_deallocatorboost::container::dtl::null_scoped_deallocator87 null_scoped_deallocator(pointer, Allocator&, std::size_t) 88 {} 89 releaseboost::container::dtl::null_scoped_deallocator90 void release() 91 {} 92 getboost::container::dtl::null_scoped_deallocator93 pointer get() const 94 { return pointer(); } 95 setboost::container::dtl::null_scoped_deallocator96 void set(const pointer &) 97 {} 98 }; 99 100 //!A deleter for scoped_ptr that deallocates the memory 101 //!allocated for an array of objects using a STL allocator. 102 template <class Allocator> 103 struct scoped_array_deallocator 104 { 105 typedef boost::container::allocator_traits<Allocator> AllocTraits; 106 typedef typename AllocTraits::pointer pointer; 107 typedef typename AllocTraits::size_type size_type; 108 scoped_array_deallocatorboost::container::dtl::scoped_array_deallocator109 scoped_array_deallocator(pointer p, Allocator& a, std::size_t length) 110 : m_ptr(p), m_alloc(a), m_length(length) {} 111 ~scoped_array_deallocatorboost::container::dtl::scoped_array_deallocator112 ~scoped_array_deallocator() 113 { if (m_ptr) m_alloc.deallocate(m_ptr, size_type(m_length)); } 114 releaseboost::container::dtl::scoped_array_deallocator115 void release() 116 { m_ptr = 0; } 117 118 private: 119 pointer m_ptr; 120 Allocator& m_alloc; 121 std::size_t m_length; 122 }; 123 124 template <class Allocator> 125 struct null_scoped_array_deallocator 126 { 127 typedef boost::container::allocator_traits<Allocator> AllocTraits; 128 typedef typename AllocTraits::pointer pointer; 129 null_scoped_array_deallocatorboost::container::dtl::null_scoped_array_deallocator130 null_scoped_array_deallocator(pointer, Allocator&, std::size_t) 131 {} 132 releaseboost::container::dtl::null_scoped_array_deallocator133 void release() 134 {} 135 }; 136 137 template <class Allocator> 138 struct scoped_destroy_deallocator 139 { 140 typedef boost::container::allocator_traits<Allocator> AllocTraits; 141 typedef typename AllocTraits::pointer pointer; 142 typedef dtl::integral_constant<unsigned, 143 boost::container::dtl:: 144 version<Allocator>::value> alloc_version; 145 scoped_destroy_deallocatorboost::container::dtl::scoped_destroy_deallocator146 scoped_destroy_deallocator(pointer p, Allocator& a) 147 : m_ptr(p), m_alloc(a) {} 148 ~scoped_destroy_deallocatorboost::container::dtl::scoped_destroy_deallocator149 ~scoped_destroy_deallocator() 150 { 151 if(m_ptr){ 152 AllocTraits::destroy(m_alloc, boost::movelib::to_raw_pointer(m_ptr)); 153 priv_deallocate(m_ptr, alloc_version()); 154 } 155 } 156 releaseboost::container::dtl::scoped_destroy_deallocator157 void release() 158 { m_ptr = 0; } 159 160 private: 161 priv_deallocateboost::container::dtl::scoped_destroy_deallocator162 void priv_deallocate(const pointer &p, version_1) 163 { AllocTraits::deallocate(m_alloc, p, 1); } 164 priv_deallocateboost::container::dtl::scoped_destroy_deallocator165 void priv_deallocate(const pointer &p, version_2) 166 { m_alloc.deallocate_one(p); } 167 168 pointer m_ptr; 169 Allocator& m_alloc; 170 }; 171 172 173 //!A deleter for scoped_ptr that destroys 174 //!an object using a STL allocator. 175 template <class Allocator> 176 struct scoped_destructor_n 177 { 178 typedef boost::container::allocator_traits<Allocator> AllocTraits; 179 typedef typename AllocTraits::pointer pointer; 180 typedef typename AllocTraits::value_type value_type; 181 scoped_destructor_nboost::container::dtl::scoped_destructor_n182 BOOST_CONTAINER_FORCEINLINE scoped_destructor_n(pointer p, Allocator& a, std::size_t n) 183 : m_p(p), m_a(a), m_n(n) 184 {} 185 releaseboost::container::dtl::scoped_destructor_n186 BOOST_CONTAINER_FORCEINLINE void release() 187 { m_p = 0; m_n = 0; } 188 increment_sizeboost::container::dtl::scoped_destructor_n189 BOOST_CONTAINER_FORCEINLINE void increment_size(std::size_t inc) 190 { m_n += inc; } 191 increment_size_backwardsboost::container::dtl::scoped_destructor_n192 BOOST_CONTAINER_FORCEINLINE void increment_size_backwards(std::size_t inc) 193 { m_n += inc; m_p -= std::ptrdiff_t(inc); } 194 shrink_forwardboost::container::dtl::scoped_destructor_n195 BOOST_CONTAINER_FORCEINLINE void shrink_forward(std::size_t inc) 196 { m_n -= inc; m_p += std::ptrdiff_t(inc); } 197 ~scoped_destructor_nboost::container::dtl::scoped_destructor_n198 ~scoped_destructor_n() 199 { 200 if(m_n){ 201 value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p); 202 do { 203 --m_n; 204 AllocTraits::destroy(m_a, raw_ptr); 205 ++raw_ptr; 206 } while(m_n); 207 } 208 } 209 210 private: 211 pointer m_p; 212 Allocator & m_a; 213 std::size_t m_n; 214 }; 215 216 //!A deleter for scoped_ptr that destroys 217 //!an object using a STL allocator. 218 template <class Allocator> 219 struct null_scoped_destructor_n 220 { 221 typedef boost::container::allocator_traits<Allocator> AllocTraits; 222 typedef typename AllocTraits::pointer pointer; 223 null_scoped_destructor_nboost::container::dtl::null_scoped_destructor_n224 BOOST_CONTAINER_FORCEINLINE null_scoped_destructor_n(pointer, Allocator&, std::size_t) 225 {} 226 increment_sizeboost::container::dtl::null_scoped_destructor_n227 BOOST_CONTAINER_FORCEINLINE void increment_size(std::size_t) 228 {} 229 increment_size_backwardsboost::container::dtl::null_scoped_destructor_n230 BOOST_CONTAINER_FORCEINLINE void increment_size_backwards(std::size_t) 231 {} 232 shrink_forwardboost::container::dtl::null_scoped_destructor_n233 BOOST_CONTAINER_FORCEINLINE void shrink_forward(std::size_t) 234 {} 235 releaseboost::container::dtl::null_scoped_destructor_n236 BOOST_CONTAINER_FORCEINLINE void release() 237 {} 238 }; 239 240 241 //!A deleter for scoped_ptr that destroys 242 //!an object using a STL allocator. 243 template <class Allocator> 244 struct scoped_destructor_range 245 { 246 typedef boost::container::allocator_traits<Allocator> AllocTraits; 247 typedef typename AllocTraits::pointer pointer; 248 typedef typename AllocTraits::value_type value_type; 249 scoped_destructor_rangeboost::container::dtl::scoped_destructor_range250 BOOST_CONTAINER_FORCEINLINE scoped_destructor_range(pointer p, pointer e, Allocator& a) 251 : m_p(p), m_e(e), m_a(a) 252 {} 253 releaseboost::container::dtl::scoped_destructor_range254 BOOST_CONTAINER_FORCEINLINE void release() 255 { m_p = pointer(); m_e = pointer(); } 256 set_endboost::container::dtl::scoped_destructor_range257 BOOST_CONTAINER_FORCEINLINE void set_end(pointer e) 258 { m_e = e; } 259 set_beginboost::container::dtl::scoped_destructor_range260 BOOST_CONTAINER_FORCEINLINE void set_begin(pointer b) 261 { m_p = b; } 262 set_rangeboost::container::dtl::scoped_destructor_range263 BOOST_CONTAINER_FORCEINLINE void set_range(pointer b, pointer e) 264 { m_p = b; m_e = e; } 265 ~scoped_destructor_rangeboost::container::dtl::scoped_destructor_range266 ~scoped_destructor_range() 267 { 268 while(m_p != m_e){ 269 value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p); 270 AllocTraits::destroy(m_a, raw_ptr); 271 ++m_p; 272 } 273 } 274 275 private: 276 pointer m_p; 277 pointer m_e; 278 Allocator & m_a; 279 }; 280 281 //!A deleter for scoped_ptr that destroys 282 //!an object using a STL allocator. 283 template <class Allocator> 284 struct null_scoped_destructor_range 285 { 286 typedef boost::container::allocator_traits<Allocator> AllocTraits; 287 typedef typename AllocTraits::pointer pointer; 288 null_scoped_destructor_rangeboost::container::dtl::null_scoped_destructor_range289 BOOST_CONTAINER_FORCEINLINE null_scoped_destructor_range(pointer, pointer, Allocator&) 290 {} 291 releaseboost::container::dtl::null_scoped_destructor_range292 BOOST_CONTAINER_FORCEINLINE void release() 293 {} 294 set_endboost::container::dtl::null_scoped_destructor_range295 BOOST_CONTAINER_FORCEINLINE void set_end(pointer) 296 {} 297 set_beginboost::container::dtl::null_scoped_destructor_range298 BOOST_CONTAINER_FORCEINLINE void set_begin(pointer) 299 {} 300 set_rangeboost::container::dtl::null_scoped_destructor_range301 BOOST_CONTAINER_FORCEINLINE void set_range(pointer, pointer) 302 {} 303 }; 304 305 306 template<class Allocator> 307 class scoped_destructor 308 { 309 typedef boost::container::allocator_traits<Allocator> AllocTraits; 310 public: 311 typedef typename Allocator::value_type value_type; scoped_destructor(Allocator & a,value_type * pv)312 BOOST_CONTAINER_FORCEINLINE scoped_destructor(Allocator &a, value_type *pv) 313 : pv_(pv), a_(a) 314 {} 315 ~scoped_destructor()316 BOOST_CONTAINER_FORCEINLINE ~scoped_destructor() 317 { 318 if(pv_){ 319 AllocTraits::destroy(a_, pv_); 320 } 321 } 322 release()323 BOOST_CONTAINER_FORCEINLINE void release() 324 { pv_ = 0; } 325 326 set(value_type * ptr)327 BOOST_CONTAINER_FORCEINLINE void set(value_type *ptr) { pv_ = ptr; } 328 get() const329 BOOST_CONTAINER_FORCEINLINE value_type *get() const { return pv_; } 330 331 private: 332 value_type *pv_; 333 Allocator &a_; 334 }; 335 336 337 template<class Allocator, class Value = typename Allocator::value_type> 338 class value_destructor 339 { 340 typedef boost::container::allocator_traits<Allocator> AllocTraits; 341 public: 342 typedef Value value_type; value_destructor(Allocator & a,value_type & rv)343 BOOST_CONTAINER_FORCEINLINE value_destructor(Allocator &a, value_type &rv) 344 : rv_(rv), a_(a) 345 {} 346 ~value_destructor()347 BOOST_CONTAINER_FORCEINLINE ~value_destructor() 348 { 349 AllocTraits::destroy(a_, &rv_); 350 } 351 352 private: 353 value_type &rv_; 354 Allocator &a_; 355 }; 356 357 template <class Allocator> 358 class allocator_destroyer 359 { 360 typedef boost::container::allocator_traits<Allocator> AllocTraits; 361 typedef typename AllocTraits::value_type value_type; 362 typedef typename AllocTraits::pointer pointer; 363 typedef dtl::integral_constant<unsigned, 364 boost::container::dtl:: 365 version<Allocator>::value> alloc_version; 366 367 private: 368 Allocator & a_; 369 370 private: priv_deallocate(const pointer & p,version_1)371 BOOST_CONTAINER_FORCEINLINE void priv_deallocate(const pointer &p, version_1) 372 { AllocTraits::deallocate(a_,p, 1); } 373 priv_deallocate(const pointer & p,version_2)374 BOOST_CONTAINER_FORCEINLINE void priv_deallocate(const pointer &p, version_2) 375 { a_.deallocate_one(p); } 376 377 public: allocator_destroyer(Allocator & a)378 BOOST_CONTAINER_FORCEINLINE explicit allocator_destroyer(Allocator &a) 379 : a_(a) 380 {} 381 operator ()(const pointer & p)382 BOOST_CONTAINER_FORCEINLINE void operator()(const pointer &p) 383 { 384 AllocTraits::destroy(a_, boost::movelib::to_raw_pointer(p)); 385 this->priv_deallocate(p, alloc_version()); 386 } 387 }; 388 389 template <class Allocator> 390 class allocator_destroyer_and_chain_builder 391 { 392 typedef allocator_traits<Allocator> allocator_traits_type; 393 typedef typename allocator_traits_type::value_type value_type; 394 typedef typename Allocator::multiallocation_chain multiallocation_chain; 395 396 Allocator & a_; 397 multiallocation_chain &c_; 398 399 public: allocator_destroyer_and_chain_builder(Allocator & a,multiallocation_chain & c)400 BOOST_CONTAINER_FORCEINLINE allocator_destroyer_and_chain_builder(Allocator &a, multiallocation_chain &c) 401 : a_(a), c_(c) 402 {} 403 operator ()(const typename Allocator::pointer & p)404 BOOST_CONTAINER_FORCEINLINE void operator()(const typename Allocator::pointer &p) 405 { 406 allocator_traits<Allocator>::destroy(a_, boost::movelib::to_raw_pointer(p)); 407 c_.push_back(p); 408 } 409 }; 410 411 template <class Allocator> 412 class allocator_multialloc_chain_node_deallocator 413 { 414 typedef allocator_traits<Allocator> allocator_traits_type; 415 typedef typename allocator_traits_type::value_type value_type; 416 typedef typename Allocator::multiallocation_chain multiallocation_chain; 417 typedef allocator_destroyer_and_chain_builder<Allocator> chain_builder; 418 419 Allocator & a_; 420 multiallocation_chain c_; 421 422 public: allocator_multialloc_chain_node_deallocator(Allocator & a)423 BOOST_CONTAINER_FORCEINLINE allocator_multialloc_chain_node_deallocator(Allocator &a) 424 : a_(a), c_() 425 {} 426 get_chain_builder()427 BOOST_CONTAINER_FORCEINLINE chain_builder get_chain_builder() 428 { return chain_builder(a_, c_); } 429 ~allocator_multialloc_chain_node_deallocator()430 BOOST_CONTAINER_FORCEINLINE ~allocator_multialloc_chain_node_deallocator() 431 { 432 a_.deallocate_individual(c_); 433 } 434 }; 435 436 } //namespace dtl { 437 } //namespace container { 438 } //namespace boost { 439 440 #include <boost/container/detail/config_end.hpp> 441 442 #endif //#ifndef BOOST_CONTAINER_DESTROYERS_HPP 443