]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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/container/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, container_detail::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 = container_detail::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_, container_detail::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_, container_detail::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 |