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 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 void release() 191 { m_p = 0; } 192 increment_sizeboost::container::dtl::scoped_destructor_n193 void increment_size(size_type inc) 194 { m_n += inc; } 195 increment_size_backwardsboost::container::dtl::scoped_destructor_n196 void increment_size_backwards(size_type inc) 197 { m_n += inc; m_p -= inc; } 198 shrink_forwardboost::container::dtl::scoped_destructor_n199 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_p) return; 205 value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p); 206 while(m_n--){ 207 AllocTraits::destroy(m_a, raw_ptr++); 208 } 209 } 210 211 private: 212 pointer m_p; 213 Allocator & m_a; 214 size_type m_n; 215 }; 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_n 221 { 222 typedef boost::container::allocator_traits<Allocator> AllocTraits; 223 typedef typename AllocTraits::pointer pointer; 224 typedef typename AllocTraits::size_type size_type; 225 null_scoped_destructor_nboost::container::dtl::null_scoped_destructor_n226 null_scoped_destructor_n(pointer, Allocator&, size_type) 227 {} 228 increment_sizeboost::container::dtl::null_scoped_destructor_n229 void increment_size(size_type) 230 {} 231 increment_size_backwardsboost::container::dtl::null_scoped_destructor_n232 void increment_size_backwards(size_type) 233 {} 234 shrink_forwardboost::container::dtl::null_scoped_destructor_n235 void shrink_forward(size_type) 236 {} 237 releaseboost::container::dtl::null_scoped_destructor_n238 void release() 239 {} 240 }; 241 242 template<class Allocator> 243 class scoped_destructor 244 { 245 typedef boost::container::allocator_traits<Allocator> AllocTraits; 246 public: 247 typedef typename Allocator::value_type value_type; scoped_destructor(Allocator & a,value_type * pv)248 scoped_destructor(Allocator &a, value_type *pv) 249 : pv_(pv), a_(a) 250 {} 251 ~scoped_destructor()252 ~scoped_destructor() 253 { 254 if(pv_){ 255 AllocTraits::destroy(a_, pv_); 256 } 257 } 258 release()259 void release() 260 { pv_ = 0; } 261 262 set(value_type * ptr)263 void set(value_type *ptr) { pv_ = ptr; } 264 get() const265 value_type *get() const { return pv_; } 266 267 private: 268 value_type *pv_; 269 Allocator &a_; 270 }; 271 272 273 template<class Allocator, class Value = typename Allocator::value_type> 274 class value_destructor 275 { 276 typedef boost::container::allocator_traits<Allocator> AllocTraits; 277 public: 278 typedef Value value_type; value_destructor(Allocator & a,value_type & rv)279 value_destructor(Allocator &a, value_type &rv) 280 : rv_(rv), a_(a) 281 {} 282 ~value_destructor()283 ~value_destructor() 284 { 285 AllocTraits::destroy(a_, &rv_); 286 } 287 288 private: 289 value_type &rv_; 290 Allocator &a_; 291 }; 292 293 template <class Allocator> 294 class allocator_destroyer 295 { 296 typedef boost::container::allocator_traits<Allocator> AllocTraits; 297 typedef typename AllocTraits::value_type value_type; 298 typedef typename AllocTraits::pointer pointer; 299 typedef dtl::integral_constant<unsigned, 300 boost::container::dtl:: 301 version<Allocator>::value> alloc_version; 302 303 private: 304 Allocator & a_; 305 306 private: priv_deallocate(const pointer & p,version_1)307 void priv_deallocate(const pointer &p, version_1) 308 { AllocTraits::deallocate(a_,p, 1); } 309 priv_deallocate(const pointer & p,version_2)310 void priv_deallocate(const pointer &p, version_2) 311 { a_.deallocate_one(p); } 312 313 public: allocator_destroyer(Allocator & a)314 explicit allocator_destroyer(Allocator &a) 315 : a_(a) 316 {} 317 operator ()(const pointer & p)318 void operator()(const pointer &p) 319 { 320 AllocTraits::destroy(a_, boost::movelib::to_raw_pointer(p)); 321 this->priv_deallocate(p, alloc_version()); 322 } 323 }; 324 325 template <class Allocator> 326 class allocator_destroyer_and_chain_builder 327 { 328 typedef allocator_traits<Allocator> allocator_traits_type; 329 typedef typename allocator_traits_type::value_type value_type; 330 typedef typename Allocator::multiallocation_chain multiallocation_chain; 331 332 Allocator & a_; 333 multiallocation_chain &c_; 334 335 public: allocator_destroyer_and_chain_builder(Allocator & a,multiallocation_chain & c)336 allocator_destroyer_and_chain_builder(Allocator &a, multiallocation_chain &c) 337 : a_(a), c_(c) 338 {} 339 operator ()(const typename Allocator::pointer & p)340 void operator()(const typename Allocator::pointer &p) 341 { 342 allocator_traits<Allocator>::destroy(a_, boost::movelib::to_raw_pointer(p)); 343 c_.push_back(p); 344 } 345 }; 346 347 template <class Allocator> 348 class allocator_multialloc_chain_node_deallocator 349 { 350 typedef allocator_traits<Allocator> allocator_traits_type; 351 typedef typename allocator_traits_type::value_type value_type; 352 typedef typename Allocator::multiallocation_chain multiallocation_chain; 353 typedef allocator_destroyer_and_chain_builder<Allocator> chain_builder; 354 355 Allocator & a_; 356 multiallocation_chain c_; 357 358 public: allocator_multialloc_chain_node_deallocator(Allocator & a)359 allocator_multialloc_chain_node_deallocator(Allocator &a) 360 : a_(a), c_() 361 {} 362 get_chain_builder()363 chain_builder get_chain_builder() 364 { return chain_builder(a_, c_); } 365 ~allocator_multialloc_chain_node_deallocator()366 ~allocator_multialloc_chain_node_deallocator() 367 { 368 a_.deallocate_individual(c_); 369 } 370 }; 371 372 } //namespace dtl { 373 } //namespace container { 374 } //namespace boost { 375 376 #include <boost/container/detail/config_end.hpp> 377 378 #endif //#ifndef BOOST_CONTAINER_DESTROYERS_HPP 379