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 container_detail {
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 container_detail::integral_constant<unsigned,
43       boost::container::container_detail::
44          version<Allocator>::value>                   alloc_version;
45 
46    private:
priv_deallocateboost::container::container_detail::scoped_deallocator47    void priv_deallocate(version_1)
48    {  m_alloc.deallocate(m_ptr, 1); }
49 
priv_deallocateboost::container::container_detail::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::container_detail::scoped_deallocator60    scoped_deallocator(pointer p, Allocator& a)
61       : m_ptr(p), m_alloc(a)
62    {}
63 
~scoped_deallocatorboost::container::container_detail::scoped_deallocator64    ~scoped_deallocator()
65    {  if (m_ptr)priv_deallocate(alloc_version());  }
66 
scoped_deallocatorboost::container::container_detail::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::container_detail::scoped_deallocator71    pointer get() const
72    {  return m_ptr;  }
73 
setboost::container::container_detail::scoped_deallocator74    void set(const pointer &p)
75    {  m_ptr = p;  }
76 
releaseboost::container::container_detail::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::container_detail::null_scoped_deallocator88    null_scoped_deallocator(pointer, Allocator&, size_type)
89    {}
90 
releaseboost::container::container_detail::null_scoped_deallocator91    void release()
92    {}
93 
getboost::container::container_detail::null_scoped_deallocator94    pointer get() const
95    {  return pointer();  }
96 
setboost::container::container_detail::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::container_detail::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::container_detail::scoped_array_deallocator113    ~scoped_array_deallocator()
114    {  if (m_ptr) m_alloc.deallocate(m_ptr, m_length);  }
115 
releaseboost::container::container_detail::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::container_detail::null_scoped_array_deallocator132    null_scoped_array_deallocator(pointer, Allocator&, size_type)
133    {}
134 
releaseboost::container::container_detail::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 container_detail::integral_constant<unsigned,
146       boost::container::container_detail::
147          version<Allocator>::value>                          alloc_version;
148 
scoped_destroy_deallocatorboost::container::container_detail::scoped_destroy_deallocator149    scoped_destroy_deallocator(pointer p, Allocator& a)
150       : m_ptr(p), m_alloc(a) {}
151 
~scoped_destroy_deallocatorboost::container::container_detail::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::container_detail::scoped_destroy_deallocator160    void release()
161    {  m_ptr = 0; }
162 
163    private:
164 
priv_deallocateboost::container::container_detail::scoped_destroy_deallocator165    void priv_deallocate(const pointer &p, version_1)
166    {  AllocTraits::deallocate(m_alloc, p, 1); }
167 
priv_deallocateboost::container::container_detail::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::container_detail::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::container_detail::scoped_destructor_n190    void release()
191    {  m_p = 0; }
192 
increment_sizeboost::container::container_detail::scoped_destructor_n193    void increment_size(size_type inc)
194    {  m_n += inc;   }
195 
increment_size_backwardsboost::container::container_detail::scoped_destructor_n196    void increment_size_backwards(size_type inc)
197    {  m_n += inc;   m_p -= inc;  }
198 
shrink_forwardboost::container::container_detail::scoped_destructor_n199    void shrink_forward(size_type inc)
200    {  m_n -= inc;   m_p += inc;  }
201 
~scoped_destructor_nboost::container::container_detail::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::container_detail::null_scoped_destructor_n226    null_scoped_destructor_n(pointer, Allocator&, size_type)
227    {}
228 
increment_sizeboost::container::container_detail::null_scoped_destructor_n229    void increment_size(size_type)
230    {}
231 
increment_size_backwardsboost::container::container_detail::null_scoped_destructor_n232    void increment_size_backwards(size_type)
233    {}
234 
shrink_forwardboost::container::container_detail::null_scoped_destructor_n235    void shrink_forward(size_type)
236    {}
237 
releaseboost::container::container_detail::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 container_detail::integral_constant<unsigned,
300       boost::container::container_detail::
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 container_detail {
373 }  //namespace container {
374 }  //namespace boost {
375 
376 #include <boost/container/detail/config_end.hpp>
377 
378 #endif   //#ifndef BOOST_CONTAINER_DESTROYERS_HPP
379