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 typedef typename AllocTraits::size_type size_type; 87 null_scoped_deallocatorboost::container::dtl::null_scoped_deallocator88 null_scoped_deallocator(pointer, Allocator&, size_type) 89 {} 90 releaseboost::container::dtl::null_scoped_deallocator91 void release() 92 {} 93 getboost::container::dtl::null_scoped_deallocator94 pointer get() const 95 { return pointer(); } 96 setboost::container::dtl::null_scoped_deallocator97 void set(const pointer &) 98 {} 99 }; 100 101 //!A deleter for scoped_ptr that deallocates the memory 102 //!allocated for an array of objects using a STL allocator. 103 template <class Allocator> 104 struct scoped_array_deallocator 105 { 106 typedef boost::container::allocator_traits<Allocator> AllocTraits; 107 typedef typename AllocTraits::pointer pointer; 108 typedef typename AllocTraits::size_type size_type; 109 scoped_array_deallocatorboost::container::dtl::scoped_array_deallocator110 scoped_array_deallocator(pointer p, Allocator& a, size_type length) 111 : m_ptr(p), m_alloc(a), m_length(length) {} 112 ~scoped_array_deallocatorboost::container::dtl::scoped_array_deallocator113 ~scoped_array_deallocator() 114 { if (m_ptr) m_alloc.deallocate(m_ptr, m_length); } 115 releaseboost::container::dtl::scoped_array_deallocator116 void release() 117 { m_ptr = 0; } 118 119 private: 120 pointer m_ptr; 121 Allocator& m_alloc; 122 size_type m_length; 123 }; 124 125 template <class Allocator> 126 struct null_scoped_array_deallocator 127 { 128 typedef boost::container::allocator_traits<Allocator> AllocTraits; 129 typedef typename AllocTraits::pointer pointer; 130 typedef typename AllocTraits::size_type size_type; 131 null_scoped_array_deallocatorboost::container::dtl::null_scoped_array_deallocator132 null_scoped_array_deallocator(pointer, Allocator&, size_type) 133 {} 134 releaseboost::container::dtl::null_scoped_array_deallocator135 void release() 136 {} 137 }; 138 139 template <class Allocator> 140 struct scoped_destroy_deallocator 141 { 142 typedef boost::container::allocator_traits<Allocator> AllocTraits; 143 typedef typename AllocTraits::pointer pointer; 144 typedef typename AllocTraits::size_type size_type; 145 typedef dtl::integral_constant<unsigned, 146 boost::container::dtl:: 147 version<Allocator>::value> alloc_version; 148 scoped_destroy_deallocatorboost::container::dtl::scoped_destroy_deallocator149 scoped_destroy_deallocator(pointer p, Allocator& a) 150 : m_ptr(p), m_alloc(a) {} 151 ~scoped_destroy_deallocatorboost::container::dtl::scoped_destroy_deallocator152 ~scoped_destroy_deallocator() 153 { 154 if(m_ptr){ 155 AllocTraits::destroy(m_alloc, boost::movelib::to_raw_pointer(m_ptr)); 156 priv_deallocate(m_ptr, alloc_version()); 157 } 158 } 159 releaseboost::container::dtl::scoped_destroy_deallocator160 void release() 161 { m_ptr = 0; } 162 163 private: 164 priv_deallocateboost::container::dtl::scoped_destroy_deallocator165 void priv_deallocate(const pointer &p, version_1) 166 { AllocTraits::deallocate(m_alloc, p, 1); } 167 priv_deallocateboost::container::dtl::scoped_destroy_deallocator168 void priv_deallocate(const pointer &p, version_2) 169 { m_alloc.deallocate_one(p); } 170 171 pointer m_ptr; 172 Allocator& m_alloc; 173 }; 174 175 176 //!A deleter for scoped_ptr that destroys 177 //!an object using a STL allocator. 178 template <class Allocator> 179 struct scoped_destructor_n 180 { 181 typedef boost::container::allocator_traits<Allocator> AllocTraits; 182 typedef typename AllocTraits::pointer pointer; 183 typedef typename AllocTraits::value_type value_type; 184 typedef typename AllocTraits::size_type size_type; 185 scoped_destructor_nboost::container::dtl::scoped_destructor_n186 BOOST_CONTAINER_FORCEINLINE scoped_destructor_n(pointer p, Allocator& a, size_type n) 187 : m_p(p), m_a(a), m_n(n) 188 {} 189 releaseboost::container::dtl::scoped_destructor_n190 BOOST_CONTAINER_FORCEINLINE void release() 191 { m_p = 0; m_n = 0; } 192 increment_sizeboost::container::dtl::scoped_destructor_n193 BOOST_CONTAINER_FORCEINLINE void increment_size(size_type inc) 194 { m_n += inc; } 195 increment_size_backwardsboost::container::dtl::scoped_destructor_n196 BOOST_CONTAINER_FORCEINLINE void increment_size_backwards(size_type inc) 197 { m_n += inc; m_p -= inc; } 198 shrink_forwardboost::container::dtl::scoped_destructor_n199 BOOST_CONTAINER_FORCEINLINE void shrink_forward(size_type inc) 200 { m_n -= inc; m_p += inc; } 201 ~scoped_destructor_nboost::container::dtl::scoped_destructor_n202 ~scoped_destructor_n() 203 { 204 if(m_n){ 205 value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p); 206 do { 207 --m_n; 208 AllocTraits::destroy(m_a, raw_ptr); 209 ++raw_ptr; 210 } while(m_n); 211 } 212 } 213 214 private: 215 pointer m_p; 216 Allocator & m_a; 217 size_type m_n; 218 }; 219 220 //!A deleter for scoped_ptr that destroys 221 //!an object using a STL allocator. 222 template <class Allocator> 223 struct null_scoped_destructor_n 224 { 225 typedef boost::container::allocator_traits<Allocator> AllocTraits; 226 typedef typename AllocTraits::pointer pointer; 227 typedef typename AllocTraits::size_type size_type; 228 null_scoped_destructor_nboost::container::dtl::null_scoped_destructor_n229 BOOST_CONTAINER_FORCEINLINE null_scoped_destructor_n(pointer, Allocator&, size_type) 230 {} 231 increment_sizeboost::container::dtl::null_scoped_destructor_n232 BOOST_CONTAINER_FORCEINLINE void increment_size(size_type) 233 {} 234 increment_size_backwardsboost::container::dtl::null_scoped_destructor_n235 BOOST_CONTAINER_FORCEINLINE void increment_size_backwards(size_type) 236 {} 237 shrink_forwardboost::container::dtl::null_scoped_destructor_n238 BOOST_CONTAINER_FORCEINLINE void shrink_forward(size_type) 239 {} 240 releaseboost::container::dtl::null_scoped_destructor_n241 BOOST_CONTAINER_FORCEINLINE void release() 242 {} 243 }; 244 245 246 //!A deleter for scoped_ptr that destroys 247 //!an object using a STL allocator. 248 template <class Allocator> 249 struct scoped_destructor_range 250 { 251 typedef boost::container::allocator_traits<Allocator> AllocTraits; 252 typedef typename AllocTraits::pointer pointer; 253 typedef typename AllocTraits::value_type value_type; 254 scoped_destructor_rangeboost::container::dtl::scoped_destructor_range255 BOOST_CONTAINER_FORCEINLINE scoped_destructor_range(pointer p, pointer e, Allocator& a) 256 : m_p(p), m_e(e), m_a(a) 257 {} 258 releaseboost::container::dtl::scoped_destructor_range259 BOOST_CONTAINER_FORCEINLINE void release() 260 { m_p = pointer(); m_e = pointer(); } 261 set_endboost::container::dtl::scoped_destructor_range262 BOOST_CONTAINER_FORCEINLINE void set_end(pointer e) 263 { m_e = e; } 264 set_beginboost::container::dtl::scoped_destructor_range265 BOOST_CONTAINER_FORCEINLINE void set_begin(pointer b) 266 { m_p = b; } 267 set_rangeboost::container::dtl::scoped_destructor_range268 BOOST_CONTAINER_FORCEINLINE void set_range(pointer b, pointer e) 269 { m_p = b; m_e = e; } 270 ~scoped_destructor_rangeboost::container::dtl::scoped_destructor_range271 ~scoped_destructor_range() 272 { 273 while(m_p != m_e){ 274 value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p); 275 AllocTraits::destroy(m_a, raw_ptr); 276 ++m_p; 277 } 278 } 279 280 private: 281 pointer m_p; 282 pointer m_e; 283 Allocator & m_a; 284 }; 285 286 //!A deleter for scoped_ptr that destroys 287 //!an object using a STL allocator. 288 template <class Allocator> 289 struct null_scoped_destructor_range 290 { 291 typedef boost::container::allocator_traits<Allocator> AllocTraits; 292 typedef typename AllocTraits::pointer pointer; 293 null_scoped_destructor_rangeboost::container::dtl::null_scoped_destructor_range294 BOOST_CONTAINER_FORCEINLINE null_scoped_destructor_range(pointer, pointer, Allocator&) 295 {} 296 releaseboost::container::dtl::null_scoped_destructor_range297 BOOST_CONTAINER_FORCEINLINE void release() 298 {} 299 set_endboost::container::dtl::null_scoped_destructor_range300 BOOST_CONTAINER_FORCEINLINE void set_end(pointer) 301 {} 302 set_beginboost::container::dtl::null_scoped_destructor_range303 BOOST_CONTAINER_FORCEINLINE void set_begin(pointer) 304 {} 305 set_rangeboost::container::dtl::null_scoped_destructor_range306 BOOST_CONTAINER_FORCEINLINE void set_range(pointer, pointer) 307 {} 308 }; 309 310 311 template<class Allocator> 312 class scoped_destructor 313 { 314 typedef boost::container::allocator_traits<Allocator> AllocTraits; 315 public: 316 typedef typename Allocator::value_type value_type; scoped_destructor(Allocator & a,value_type * pv)317 BOOST_CONTAINER_FORCEINLINE scoped_destructor(Allocator &a, value_type *pv) 318 : pv_(pv), a_(a) 319 {} 320 ~scoped_destructor()321 BOOST_CONTAINER_FORCEINLINE ~scoped_destructor() 322 { 323 if(pv_){ 324 AllocTraits::destroy(a_, pv_); 325 } 326 } 327 release()328 BOOST_CONTAINER_FORCEINLINE void release() 329 { pv_ = 0; } 330 331 set(value_type * ptr)332 BOOST_CONTAINER_FORCEINLINE void set(value_type *ptr) { pv_ = ptr; } 333 get() const334 BOOST_CONTAINER_FORCEINLINE value_type *get() const { return pv_; } 335 336 private: 337 value_type *pv_; 338 Allocator &a_; 339 }; 340 341 342 template<class Allocator, class Value = typename Allocator::value_type> 343 class value_destructor 344 { 345 typedef boost::container::allocator_traits<Allocator> AllocTraits; 346 public: 347 typedef Value value_type; value_destructor(Allocator & a,value_type & rv)348 BOOST_CONTAINER_FORCEINLINE value_destructor(Allocator &a, value_type &rv) 349 : rv_(rv), a_(a) 350 {} 351 ~value_destructor()352 BOOST_CONTAINER_FORCEINLINE ~value_destructor() 353 { 354 AllocTraits::destroy(a_, &rv_); 355 } 356 357 private: 358 value_type &rv_; 359 Allocator &a_; 360 }; 361 362 template <class Allocator> 363 class allocator_destroyer 364 { 365 typedef boost::container::allocator_traits<Allocator> AllocTraits; 366 typedef typename AllocTraits::value_type value_type; 367 typedef typename AllocTraits::pointer pointer; 368 typedef dtl::integral_constant<unsigned, 369 boost::container::dtl:: 370 version<Allocator>::value> alloc_version; 371 372 private: 373 Allocator & a_; 374 375 private: priv_deallocate(const pointer & p,version_1)376 BOOST_CONTAINER_FORCEINLINE void priv_deallocate(const pointer &p, version_1) 377 { AllocTraits::deallocate(a_,p, 1); } 378 priv_deallocate(const pointer & p,version_2)379 BOOST_CONTAINER_FORCEINLINE void priv_deallocate(const pointer &p, version_2) 380 { a_.deallocate_one(p); } 381 382 public: allocator_destroyer(Allocator & a)383 BOOST_CONTAINER_FORCEINLINE explicit allocator_destroyer(Allocator &a) 384 : a_(a) 385 {} 386 operator ()(const pointer & p)387 BOOST_CONTAINER_FORCEINLINE void operator()(const pointer &p) 388 { 389 AllocTraits::destroy(a_, boost::movelib::to_raw_pointer(p)); 390 this->priv_deallocate(p, alloc_version()); 391 } 392 }; 393 394 template <class Allocator> 395 class allocator_destroyer_and_chain_builder 396 { 397 typedef allocator_traits<Allocator> allocator_traits_type; 398 typedef typename allocator_traits_type::value_type value_type; 399 typedef typename Allocator::multiallocation_chain multiallocation_chain; 400 401 Allocator & a_; 402 multiallocation_chain &c_; 403 404 public: allocator_destroyer_and_chain_builder(Allocator & a,multiallocation_chain & c)405 BOOST_CONTAINER_FORCEINLINE allocator_destroyer_and_chain_builder(Allocator &a, multiallocation_chain &c) 406 : a_(a), c_(c) 407 {} 408 operator ()(const typename Allocator::pointer & p)409 BOOST_CONTAINER_FORCEINLINE void operator()(const typename Allocator::pointer &p) 410 { 411 allocator_traits<Allocator>::destroy(a_, boost::movelib::to_raw_pointer(p)); 412 c_.push_back(p); 413 } 414 }; 415 416 template <class Allocator> 417 class allocator_multialloc_chain_node_deallocator 418 { 419 typedef allocator_traits<Allocator> allocator_traits_type; 420 typedef typename allocator_traits_type::value_type value_type; 421 typedef typename Allocator::multiallocation_chain multiallocation_chain; 422 typedef allocator_destroyer_and_chain_builder<Allocator> chain_builder; 423 424 Allocator & a_; 425 multiallocation_chain c_; 426 427 public: allocator_multialloc_chain_node_deallocator(Allocator & a)428 BOOST_CONTAINER_FORCEINLINE allocator_multialloc_chain_node_deallocator(Allocator &a) 429 : a_(a), c_() 430 {} 431 get_chain_builder()432 BOOST_CONTAINER_FORCEINLINE chain_builder get_chain_builder() 433 { return chain_builder(a_, c_); } 434 ~allocator_multialloc_chain_node_deallocator()435 BOOST_CONTAINER_FORCEINLINE ~allocator_multialloc_chain_node_deallocator() 436 { 437 a_.deallocate_individual(c_); 438 } 439 }; 440 441 } //namespace dtl { 442 } //namespace container { 443 } //namespace boost { 444 445 #include <boost/container/detail/config_end.hpp> 446 447 #endif //#ifndef BOOST_CONTAINER_DESTROYERS_HPP 448