• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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