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: |
47 | void priv_deallocate(version_1) |
48 | { m_alloc.deallocate(m_ptr, 1); } |
49 | |
50 | 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 | |
60 | scoped_deallocator(pointer p, Allocator& a) |
61 | : m_ptr(p), m_alloc(a) |
62 | {} |
63 | |
64 | ~scoped_deallocator() |
65 | { if (m_ptr)priv_deallocate(alloc_version()); } |
66 | |
67 | scoped_deallocator(BOOST_RV_REF(scoped_deallocator) o) |
68 | : m_ptr(o.m_ptr), m_alloc(o.m_alloc) |
69 | { o.release(); } |
70 | |
71 | pointer get() const |
72 | { return m_ptr; } |
73 | |
74 | void set(const pointer &p) |
75 | { m_ptr = p; } |
76 | |
77 | 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 | |
88 | null_scoped_deallocator(pointer, Allocator&, size_type) |
89 | {} |
90 | |
91 | void release() |
92 | {} |
93 | |
94 | pointer get() const |
95 | { return pointer(); } |
96 | |
97 | 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 | |
110 | scoped_array_deallocator(pointer p, Allocator& a, size_type length) |
111 | : m_ptr(p), m_alloc(a), m_length(length) {} |
112 | |
113 | ~scoped_array_deallocator() |
114 | { if (m_ptr) m_alloc.deallocate(m_ptr, m_length); } |
115 | |
116 | 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 | |
132 | null_scoped_array_deallocator(pointer, Allocator&, size_type) |
133 | {} |
134 | |
135 | 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 | |
149 | scoped_destroy_deallocator(pointer p, Allocator& a) |
150 | : m_ptr(p), m_alloc(a) {} |
151 | |
152 | ~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 | |
160 | void release() |
161 | { m_ptr = 0; } |
162 | |
163 | private: |
164 | |
165 | void priv_deallocate(const pointer &p, version_1) |
166 | { AllocTraits::deallocate(m_alloc, p, 1); } |
167 | |
168 | 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 | |
186 | scoped_destructor_n(pointer p, Allocator& a, size_type n) |
187 | : m_p(p), m_a(a), m_n(n) |
188 | {} |
189 | |
190 | void release() |
191 | { m_p = 0; } |
192 | |
193 | void increment_size(size_type inc) |
194 | { m_n += inc; } |
195 | |
196 | void increment_size_backwards(size_type inc) |
197 | { m_n += inc; m_p -= inc; } |
198 | |
199 | void shrink_forward(size_type inc) |
200 | { m_n -= inc; m_p += inc; } |
201 | |
202 | ~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 | |
226 | null_scoped_destructor_n(pointer, Allocator&, size_type) |
227 | {} |
228 | |
229 | void increment_size(size_type) |
230 | {} |
231 | |
232 | void increment_size_backwards(size_type) |
233 | {} |
234 | |
235 | void shrink_forward(size_type) |
236 | {} |
237 | |
238 | 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; |
248 | scoped_destructor(Allocator &a, value_type *pv) |
249 | : pv_(pv), a_(a) |
250 | {} |
251 | |
252 | ~scoped_destructor() |
253 | { |
254 | if(pv_){ |
255 | AllocTraits::destroy(a_, pv_); |
256 | } |
257 | } |
258 | |
259 | void release() |
260 | { pv_ = 0; } |
261 | |
262 | |
263 | void set(value_type *ptr) { pv_ = ptr; } |
264 | |
265 | value_type *get() const { return pv_; } |
266 | |
267 | private: |
268 | value_type *pv_; |
269 | Allocator &a_; |
270 | }; |
271 | |
272 | |
273 | template<class Allocator> |
274 | class value_destructor |
275 | { |
276 | typedef boost::container::allocator_traits<Allocator> AllocTraits; |
277 | public: |
278 | typedef typename Allocator::value_type value_type; |
279 | value_destructor(Allocator &a, value_type &rv) |
280 | : rv_(rv), a_(a) |
281 | {} |
282 | |
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: |
307 | void priv_deallocate(const pointer &p, version_1) |
308 | { AllocTraits::deallocate(a_,p, 1); } |
309 | |
310 | void priv_deallocate(const pointer &p, version_2) |
311 | { a_.deallocate_one(p); } |
312 | |
313 | public: |
314 | explicit allocator_destroyer(Allocator &a) |
315 | : a_(a) |
316 | {} |
317 | |
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: |
336 | allocator_destroyer_and_chain_builder(Allocator &a, multiallocation_chain &c) |
337 | : a_(a), c_(c) |
338 | {} |
339 | |
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: |
359 | allocator_multialloc_chain_node_deallocator(Allocator &a) |
360 | : a_(a), c_() |
361 | {} |
362 | |
363 | chain_builder get_chain_builder() |
364 | { return chain_builder(a_, c_); } |
365 | |
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 | |