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