]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // | |
3 | // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost | |
4 | // Software License, Version 1.0. (See accompanying file | |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | // | |
7 | // See http://www.boost.org/libs/container for documentation. | |
8 | // | |
9 | ////////////////////////////////////////////////////////////////////////////// | |
10 | ||
11 | #ifndef BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_ | |
12 | #define BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_ | |
13 | ||
14 | #ifndef BOOST_CONFIG_HPP | |
15 | # include <boost/config.hpp> | |
16 | #endif | |
17 | ||
18 | #if defined(BOOST_HAS_PRAGMA_ONCE) | |
19 | # pragma once | |
20 | #endif | |
21 | ||
22 | #include <boost/container/detail/config_begin.hpp> | |
23 | #include <boost/container/detail/workaround.hpp> | |
24 | ||
25 | // container | |
26 | #include <boost/container/allocator_traits.hpp> | |
27 | // container/detail | |
28 | #include <boost/container/detail/addressof.hpp> | |
29 | #include <boost/container/detail/alloc_helpers.hpp> | |
30 | #include <boost/container/detail/allocator_version_traits.hpp> | |
31 | #include <boost/container/detail/construct_in_place.hpp> | |
32 | #include <boost/container/detail/destroyers.hpp> | |
b32b8144 | 33 | #include <boost/move/detail/iterator_to_raw_pointer.hpp> |
7c673cae FG |
34 | #include <boost/container/detail/mpl.hpp> |
35 | #include <boost/container/detail/placement_new.hpp> | |
b32b8144 | 36 | #include <boost/move/detail/to_raw_pointer.hpp> |
7c673cae FG |
37 | #include <boost/container/detail/type_traits.hpp> |
38 | #include <boost/container/detail/version_type.hpp> | |
1e59de90 | 39 | #include <boost/container/detail/is_pair.hpp> |
7c673cae FG |
40 | // intrusive |
41 | #include <boost/intrusive/detail/mpl.hpp> | |
42 | #include <boost/intrusive/options.hpp> | |
43 | // move | |
44 | #include <boost/move/utility_core.hpp> | |
45 | #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
46 | #include <boost/move/detail/fwd_macros.hpp> | |
47 | #endif | |
48 | // other | |
49 | #include <boost/core/no_exceptions_support.hpp> | |
50 | ||
51 | ||
52 | namespace boost { | |
53 | namespace container { | |
1e59de90 TL |
54 | |
55 | //This trait is used to type-pun std::pair because in C++03 | |
56 | //compilers std::pair is useless for C++11 features | |
57 | template<class T, bool = dtl::is_pair<T>::value > | |
58 | struct node_internal_data_type | |
59 | { | |
60 | typedef T type; | |
61 | }; | |
62 | ||
63 | template<class T> | |
64 | struct node_internal_data_type< T, true> | |
65 | { | |
66 | typedef dtl::pair< typename dtl::remove_const<typename T::first_type>::type | |
67 | , typename T::second_type> | |
68 | type; | |
69 | }; | |
70 | ||
71 | template <class T, class HookDefiner> | |
72 | struct base_node | |
73 | : public HookDefiner::type | |
74 | { | |
75 | public: | |
76 | typedef T value_type; | |
77 | typedef typename node_internal_data_type<T>::type internal_type; | |
78 | typedef typename HookDefiner::type hook_type; | |
79 | ||
80 | typedef typename dtl::aligned_storage<sizeof(T), dtl::alignment_of<T>::value>::type storage_t; | |
81 | storage_t m_storage; | |
82 | ||
83 | #if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000) | |
84 | #pragma GCC diagnostic push | |
85 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" | |
86 | #define BOOST_CONTAINER_DISABLE_ALIASING_WARNING | |
87 | # endif | |
88 | public: | |
89 | ||
90 | #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
91 | ||
92 | template<class Alloc, class ...Args> | |
93 | explicit base_node(Alloc &a, Args &&...args) | |
94 | : hook_type() | |
95 | { | |
96 | ::boost::container::allocator_traits<Alloc>::construct | |
97 | (a, &this->get_real_data(), ::boost::forward<Args>(args)...); | |
98 | } | |
99 | ||
100 | #else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
101 | ||
102 | #define BOOST_CONTAINER_BASE_NODE_CONSTRUCT_IMPL(N) \ | |
103 | template< class Alloc BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \ | |
104 | explicit base_node(Alloc &a BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ | |
105 | : hook_type()\ | |
106 | {\ | |
107 | ::boost::container::allocator_traits<Alloc>::construct\ | |
108 | (a, &this->get_real_data() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ | |
109 | }\ | |
110 | // | |
111 | BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_BASE_NODE_CONSTRUCT_IMPL) | |
112 | #undef BOOST_CONTAINER_BASE_NODE_CONSTRUCT_IMPL | |
113 | ||
114 | #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
115 | ||
116 | template<class Alloc, class It> | |
117 | explicit base_node(iterator_arg_t, Alloc &a, It it) | |
118 | : hook_type() | |
119 | { | |
120 | ::boost::container::construct_in_place(a, &this->get_real_data(), it); | |
121 | } | |
122 | ||
123 | BOOST_CONTAINER_FORCEINLINE T &get_data() | |
124 | { return *move_detail::force_ptr<T*>(this->m_storage.data); } | |
125 | ||
126 | BOOST_CONTAINER_FORCEINLINE const T &get_data() const | |
127 | { return *move_detail::force_ptr<const T*>(this->m_storage.data); } | |
128 | ||
129 | BOOST_CONTAINER_FORCEINLINE internal_type &get_real_data() | |
130 | { return *move_detail::force_ptr<internal_type*>(this->m_storage.data); } | |
131 | ||
132 | BOOST_CONTAINER_FORCEINLINE const internal_type &get_real_data() const | |
133 | { return *move_detail::force_ptr<const internal_type*>(this->m_storage.data); } | |
134 | ||
135 | #if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING) | |
136 | #pragma GCC diagnostic pop | |
137 | #undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING | |
138 | # endif | |
139 | ||
140 | template<class Alloc> | |
141 | void destructor(Alloc &a) BOOST_NOEXCEPT | |
142 | { | |
143 | allocator_traits<Alloc>::destroy | |
144 | (a, &this->get_real_data()); | |
145 | this->~base_node(); | |
146 | } | |
147 | ||
148 | template<class Pair> | |
149 | BOOST_CONTAINER_FORCEINLINE | |
150 | typename dtl::enable_if< dtl::is_pair<Pair>, void >::type | |
151 | do_assign(const Pair &p) | |
152 | { | |
153 | typedef typename Pair::first_type first_type; | |
154 | const_cast<typename dtl::remove_const<first_type>::type &>(this->get_real_data().first) = p.first; | |
155 | this->get_real_data().second = p.second; | |
156 | } | |
157 | ||
158 | template<class V> | |
159 | BOOST_CONTAINER_FORCEINLINE | |
160 | typename dtl::disable_if< dtl::is_pair<V>, void >::type | |
161 | do_assign(const V &v) | |
162 | { this->get_real_data() = v; } | |
163 | ||
164 | template<class Pair> | |
165 | BOOST_CONTAINER_FORCEINLINE | |
166 | typename dtl::enable_if< dtl::is_pair<Pair>, void >::type | |
167 | do_move_assign(Pair &p) | |
168 | { | |
169 | typedef typename Pair::first_type first_type; | |
170 | const_cast<first_type&>(this->get_real_data().first) = ::boost::move(p.first); | |
171 | this->get_real_data().second = ::boost::move(p.second); | |
172 | } | |
173 | ||
174 | template<class V> | |
175 | BOOST_CONTAINER_FORCEINLINE | |
176 | typename dtl::disable_if< dtl::is_pair<V>, void >::type | |
177 | do_move_assign(V &v) | |
178 | { this->get_real_data() = ::boost::move(v); } | |
179 | ||
180 | private: | |
181 | base_node(); | |
182 | ||
183 | BOOST_CONTAINER_FORCEINLINE ~base_node() | |
184 | { } | |
185 | }; | |
186 | ||
187 | ||
11fdf7f2 | 188 | namespace dtl { |
7c673cae | 189 | |
92f5a8d4 TL |
190 | BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(key_compare) |
191 | BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(key_equal) | |
192 | BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(hasher) | |
7c673cae FG |
193 | BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(predicate_type) |
194 | ||
195 | template<class Allocator, class ICont> | |
196 | struct node_alloc_holder | |
92f5a8d4 TL |
197 | : public allocator_traits<Allocator>::template |
198 | portable_rebind_alloc<typename ICont::value_type>::type //NodeAlloc | |
7c673cae FG |
199 | { |
200 | //If the intrusive container is an associative container, obtain the predicate, which will | |
92f5a8d4 | 201 | //be of type node_compare<>. If not an associative container val_compare will be a "nat" type. |
7c673cae | 202 | typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT |
11fdf7f2 | 203 | ( boost::container::dtl:: |
92f5a8d4 | 204 | , ICont, key_compare, dtl::nat) intrusive_val_compare; |
7c673cae | 205 | //In that case obtain the value predicate from the node predicate via predicate_type |
92f5a8d4 | 206 | //if intrusive_val_compare is node_compare<>, nat otherwise |
7c673cae | 207 | typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT |
11fdf7f2 | 208 | ( boost::container::dtl:: |
92f5a8d4 TL |
209 | , intrusive_val_compare |
210 | , predicate_type, dtl::nat) val_compare; | |
211 | ||
212 | //If the intrusive container is a hash container, obtain the predicate, which will | |
213 | //be of type node_compare<>. If not an associative container val_equal will be a "nat" type. | |
214 | typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT | |
215 | (boost::container::dtl:: | |
216 | , ICont, key_equal, dtl::nat2) intrusive_val_equal; | |
217 | typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT | |
218 | (boost::container::dtl:: | |
219 | , ICont, hasher, dtl::nat3) intrusive_val_hasher; | |
220 | //In that case obtain the value predicate from the node predicate via predicate_type | |
221 | //if intrusive_val_compare is node_compare<>, nat otherwise | |
222 | typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT | |
223 | (boost::container::dtl:: | |
224 | , intrusive_val_equal | |
225 | , predicate_type, dtl::nat2) val_equal; | |
226 | typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT | |
227 | (boost::container::dtl:: | |
228 | , intrusive_val_hasher | |
229 | , predicate_type, dtl::nat3) val_hasher; | |
7c673cae FG |
230 | |
231 | typedef allocator_traits<Allocator> allocator_traits_type; | |
92f5a8d4 | 232 | typedef typename allocator_traits_type::value_type val_type; |
7c673cae FG |
233 | typedef ICont intrusive_container; |
234 | typedef typename ICont::value_type Node; | |
235 | typedef typename allocator_traits_type::template | |
236 | portable_rebind_alloc<Node>::type NodeAlloc; | |
237 | typedef allocator_traits<NodeAlloc> node_allocator_traits_type; | |
11fdf7f2 | 238 | typedef dtl::allocator_version_traits<NodeAlloc> node_allocator_version_traits_type; |
7c673cae FG |
239 | typedef Allocator ValAlloc; |
240 | typedef typename node_allocator_traits_type::pointer NodePtr; | |
11fdf7f2 | 241 | typedef dtl::scoped_deallocator<NodeAlloc> Deallocator; |
7c673cae FG |
242 | typedef typename node_allocator_traits_type::size_type size_type; |
243 | typedef typename node_allocator_traits_type::difference_type difference_type; | |
11fdf7f2 TL |
244 | typedef dtl::integral_constant<unsigned, |
245 | boost::container::dtl:: | |
7c673cae FG |
246 | version<NodeAlloc>::value> alloc_version; |
247 | typedef typename ICont::iterator icont_iterator; | |
248 | typedef typename ICont::const_iterator icont_citerator; | |
1e59de90 | 249 | typedef allocator_node_destroyer<NodeAlloc> Destroyer; |
7c673cae FG |
250 | typedef allocator_traits<NodeAlloc> NodeAllocTraits; |
251 | typedef allocator_version_traits<NodeAlloc> AllocVersionTraits; | |
252 | ||
253 | private: | |
254 | BOOST_COPYABLE_AND_MOVABLE(node_alloc_holder) | |
255 | ||
256 | public: | |
257 | ||
258 | //Constructors for sequence containers | |
259 | node_alloc_holder() | |
7c673cae FG |
260 | {} |
261 | ||
262 | explicit node_alloc_holder(const ValAlloc &a) | |
92f5a8d4 | 263 | : NodeAlloc(a) |
7c673cae FG |
264 | {} |
265 | ||
b32b8144 | 266 | //Constructors for associative containers |
92f5a8d4 TL |
267 | node_alloc_holder(const val_compare &c, const ValAlloc &a) |
268 | : NodeAlloc(a), m_icont(typename ICont::key_compare(c)) | |
269 | {} | |
270 | ||
271 | node_alloc_holder(const val_hasher &hf, const val_equal &eql, const ValAlloc &a) | |
272 | : NodeAlloc(a) | |
273 | , m_icont(typename ICont::bucket_traits() | |
274 | , typename ICont::hasher(hf) | |
275 | , typename ICont::key_equal(eql)) | |
276 | {} | |
277 | ||
278 | node_alloc_holder(const val_hasher &hf, const ValAlloc &a) | |
279 | : NodeAlloc(a) | |
280 | , m_icont(typename ICont::bucket_traits() | |
281 | , typename ICont::hasher(hf) | |
282 | , typename ICont::key_equal()) | |
283 | {} | |
284 | ||
285 | node_alloc_holder(const val_hasher &hf) | |
286 | : m_icont(typename ICont::bucket_traits() | |
287 | , typename ICont::hasher(hf) | |
288 | , typename ICont::key_equal()) | |
b32b8144 FG |
289 | {} |
290 | ||
7c673cae | 291 | explicit node_alloc_holder(const node_alloc_holder &x) |
92f5a8d4 | 292 | : NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc())) |
7c673cae FG |
293 | {} |
294 | ||
92f5a8d4 TL |
295 | node_alloc_holder(const node_alloc_holder &x, const val_compare &c) |
296 | : NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc())) | |
297 | , m_icont(typename ICont::key_compare(c)) | |
298 | {} | |
299 | ||
300 | node_alloc_holder(const node_alloc_holder &x, const val_hasher &hf, const val_equal &eql) | |
301 | : NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc())) | |
302 | , m_icont( typename ICont::bucket_traits() | |
303 | , typename ICont::hasher(hf) | |
304 | , typename ICont::key_equal(eql)) | |
305 | {} | |
306 | ||
307 | node_alloc_holder(const val_hasher &hf, const val_equal &eql) | |
308 | : m_icont(typename ICont::bucket_traits() | |
309 | , typename ICont::hasher(hf) | |
310 | , typename ICont::key_equal(eql)) | |
b32b8144 FG |
311 | {} |
312 | ||
7c673cae | 313 | explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x) |
1e59de90 | 314 | : NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc())) |
7c673cae FG |
315 | { this->icont().swap(x.icont()); } |
316 | ||
92f5a8d4 TL |
317 | explicit node_alloc_holder(const val_compare &c) |
318 | : m_icont(typename ICont::key_compare(c)) | |
7c673cae FG |
319 | {} |
320 | ||
321 | //helpers for move assignments | |
92f5a8d4 | 322 | explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const val_compare &c) |
1e59de90 | 323 | : NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc())), m_icont(typename ICont::key_compare(c)) |
7c673cae FG |
324 | { this->icont().swap(x.icont()); } |
325 | ||
92f5a8d4 | 326 | explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const val_hasher &hf, const val_equal &eql) |
1e59de90 | 327 | : NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc())) |
92f5a8d4 TL |
328 | , m_icont( typename ICont::bucket_traits() |
329 | , typename ICont::hasher(hf) | |
330 | , typename ICont::key_equal(eql)) | |
1e59de90 | 331 | { this->icont().swap(BOOST_MOVE_TO_LV(x).icont()); } |
92f5a8d4 | 332 | |
7c673cae FG |
333 | void copy_assign_alloc(const node_alloc_holder &x) |
334 | { | |
11fdf7f2 | 335 | dtl::bool_<allocator_traits_type::propagate_on_container_copy_assignment::value> flag; |
92f5a8d4 TL |
336 | dtl::assign_alloc( static_cast<NodeAlloc &>(*this) |
337 | , static_cast<const NodeAlloc &>(x), flag); | |
7c673cae FG |
338 | } |
339 | ||
340 | void move_assign_alloc( node_alloc_holder &x) | |
341 | { | |
11fdf7f2 | 342 | dtl::bool_<allocator_traits_type::propagate_on_container_move_assignment::value> flag; |
92f5a8d4 TL |
343 | dtl::move_alloc( static_cast<NodeAlloc &>(*this) |
344 | , static_cast<NodeAlloc &>(x), flag); | |
7c673cae FG |
345 | } |
346 | ||
347 | ~node_alloc_holder() | |
348 | { this->clear(alloc_version()); } | |
349 | ||
350 | size_type max_size() const | |
351 | { return allocator_traits_type::max_size(this->node_alloc()); } | |
352 | ||
353 | NodePtr allocate_one() | |
354 | { return AllocVersionTraits::allocate_one(this->node_alloc()); } | |
355 | ||
356 | void deallocate_one(const NodePtr &p) | |
357 | { AllocVersionTraits::deallocate_one(this->node_alloc(), p); } | |
358 | ||
359 | #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
360 | ||
361 | template<class ...Args> | |
362 | NodePtr create_node(Args &&...args) | |
363 | { | |
364 | NodePtr p = this->allocate_one(); | |
1e59de90 TL |
365 | NodeAlloc &nalloc = this->node_alloc(); |
366 | Deallocator node_deallocator(p, nalloc); | |
367 | ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) | |
368 | Node(nalloc, boost::forward<Args>(args)...); | |
369 | node_deallocator.release(); | |
7c673cae FG |
370 | return (p); |
371 | } | |
372 | ||
373 | #else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
374 | ||
375 | #define BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL(N) \ | |
376 | BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ | |
377 | NodePtr create_node(BOOST_MOVE_UREF##N)\ | |
378 | {\ | |
379 | NodePtr p = this->allocate_one();\ | |
1e59de90 TL |
380 | NodeAlloc &nalloc = this->node_alloc();\ |
381 | Deallocator node_deallocator(p, nalloc);\ | |
382 | ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())\ | |
383 | Node(nalloc BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ | |
384 | node_deallocator.release();\ | |
7c673cae FG |
385 | return (p);\ |
386 | }\ | |
387 | // | |
388 | BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL) | |
389 | #undef BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL | |
390 | ||
391 | #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
392 | ||
393 | template<class It> | |
394 | NodePtr create_node_from_it(const It &it) | |
395 | { | |
396 | NodePtr p = this->allocate_one(); | |
1e59de90 TL |
397 | NodeAlloc &nalloc = this->node_alloc(); |
398 | Deallocator node_deallocator(p, nalloc); | |
399 | ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) | |
400 | Node(iterator_arg_t(), nalloc, it); | |
401 | node_deallocator.release(); | |
7c673cae FG |
402 | return (p); |
403 | } | |
404 | ||
405 | template<class KeyConvertible> | |
406 | NodePtr create_node_from_key(BOOST_FWD_REF(KeyConvertible) key) | |
407 | { | |
408 | NodePtr p = this->allocate_one(); | |
7c673cae | 409 | BOOST_TRY{ |
92f5a8d4 TL |
410 | ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node; |
411 | NodeAlloc &na = this->node_alloc(); | |
412 | node_allocator_traits_type::construct | |
413 | (na, dtl::addressof(p->get_real_data().first), boost::forward<KeyConvertible>(key)); | |
414 | BOOST_TRY{ | |
415 | node_allocator_traits_type::construct(na, dtl::addressof(p->get_real_data().second)); | |
416 | } | |
417 | BOOST_CATCH(...){ | |
418 | node_allocator_traits_type::destroy(na, dtl::addressof(p->get_real_data().first)); | |
419 | BOOST_RETHROW; | |
420 | } | |
421 | BOOST_CATCH_END | |
7c673cae | 422 | } |
92f5a8d4 TL |
423 | BOOST_CATCH(...) { |
424 | p->destroy_header(); | |
425 | this->node_alloc().deallocate(p, 1); | |
426 | BOOST_RETHROW | |
7c673cae FG |
427 | } |
428 | BOOST_CATCH_END | |
7c673cae FG |
429 | return (p); |
430 | } | |
431 | ||
432 | void destroy_node(const NodePtr &nodep) | |
433 | { | |
1e59de90 | 434 | boost::movelib::to_raw_pointer(nodep)->destructor(this->node_alloc()); |
7c673cae FG |
435 | this->deallocate_one(nodep); |
436 | } | |
437 | ||
438 | void swap(node_alloc_holder &x) | |
439 | { | |
440 | this->icont().swap(x.icont()); | |
11fdf7f2 TL |
441 | dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag; |
442 | dtl::swap_alloc(this->node_alloc(), x.node_alloc(), flag); | |
7c673cae FG |
443 | } |
444 | ||
445 | template<class FwdIterator, class Inserter> | |
446 | void allocate_many_and_construct | |
1e59de90 | 447 | (FwdIterator beg, size_type n, Inserter inserter) |
7c673cae FG |
448 | { |
449 | if(n){ | |
92f5a8d4 | 450 | typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain_t; |
7c673cae FG |
451 | |
452 | //Try to allocate memory in a single block | |
92f5a8d4 TL |
453 | typedef typename multiallocation_chain_t::iterator multialloc_iterator_t; |
454 | multiallocation_chain_t chain; | |
7c673cae | 455 | NodeAlloc &nalloc = this->node_alloc(); |
92f5a8d4 TL |
456 | node_allocator_version_traits_type::allocate_individual(nalloc, n, chain); |
457 | multialloc_iterator_t itbeg = chain.begin(); | |
458 | multialloc_iterator_t itlast = chain.last(); | |
459 | chain.clear(); | |
460 | ||
7c673cae | 461 | Node *p = 0; |
92f5a8d4 | 462 | BOOST_TRY{ |
7c673cae | 463 | Deallocator node_deallocator(NodePtr(), nalloc); |
1e59de90 | 464 | dtl::scoped_node_destructor<NodeAlloc> sdestructor(nalloc, 0); |
92f5a8d4 TL |
465 | while(n){ |
466 | --n; | |
b32b8144 | 467 | p = boost::movelib::iterator_to_raw_pointer(itbeg); |
92f5a8d4 TL |
468 | ++itbeg; //Increment iterator before overwriting pointed memory |
469 | //This does not throw | |
1e59de90 TL |
470 | ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) |
471 | Node(iterator_arg_t(), nalloc, beg); | |
7c673cae FG |
472 | sdestructor.set(p); |
473 | ++beg; | |
7c673cae FG |
474 | //This can throw in some containers (predicate might throw). |
475 | //(sdestructor will destruct the node and node_deallocator will deallocate it in case of exception) | |
476 | inserter(*p); | |
1e59de90 | 477 | sdestructor.release(); |
7c673cae FG |
478 | } |
479 | sdestructor.release(); | |
480 | node_deallocator.release(); | |
481 | } | |
482 | BOOST_CATCH(...){ | |
92f5a8d4 TL |
483 | chain.incorporate_after(chain.last(), &*itbeg, &*itlast, n); |
484 | node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), chain); | |
7c673cae FG |
485 | BOOST_RETHROW |
486 | } | |
487 | BOOST_CATCH_END | |
488 | } | |
489 | } | |
490 | ||
491 | void clear(version_1) | |
492 | { this->icont().clear_and_dispose(Destroyer(this->node_alloc())); } | |
493 | ||
494 | void clear(version_2) | |
495 | { | |
496 | typename NodeAlloc::multiallocation_chain chain; | |
1e59de90 | 497 | allocator_node_destroyer_and_chain_builder<NodeAlloc> builder(this->node_alloc(), chain); |
7c673cae FG |
498 | this->icont().clear_and_dispose(builder); |
499 | //BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled<typename NodeAlloc::multiallocation_chain>::value == true)); | |
500 | if(!chain.empty()) | |
501 | this->node_alloc().deallocate_individual(chain); | |
502 | } | |
503 | ||
504 | icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, version_1) | |
505 | { return this->icont().erase_and_dispose(first, last, Destroyer(this->node_alloc())); } | |
506 | ||
507 | icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, version_2) | |
508 | { | |
7c673cae | 509 | NodeAlloc & nalloc = this->node_alloc(); |
1e59de90 TL |
510 | typename NodeAlloc::multiallocation_chain chain; |
511 | allocator_node_destroyer_and_chain_builder<NodeAlloc> chain_builder(nalloc, chain); | |
7c673cae FG |
512 | icont_iterator ret_it = this->icont().erase_and_dispose(first, last, chain_builder); |
513 | nalloc.deallocate_individual(chain); | |
514 | return ret_it; | |
515 | } | |
516 | ||
517 | template<class Key, class Comparator> | |
518 | size_type erase_key(const Key& k, const Comparator &comp, version_1) | |
519 | { return this->icont().erase_and_dispose(k, comp, Destroyer(this->node_alloc())); } | |
520 | ||
521 | template<class Key, class Comparator> | |
522 | size_type erase_key(const Key& k, const Comparator &comp, version_2) | |
523 | { | |
524 | allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc()); | |
525 | return this->icont().erase_and_dispose(k, comp, chain_holder.get_chain_builder()); | |
526 | } | |
527 | ||
528 | protected: | |
529 | struct cloner | |
530 | { | |
531 | explicit cloner(node_alloc_holder &holder) | |
532 | : m_holder(holder) | |
533 | {} | |
534 | ||
535 | NodePtr operator()(const Node &other) const | |
92f5a8d4 | 536 | { return m_holder.create_node(other.get_real_data()); } |
7c673cae FG |
537 | |
538 | node_alloc_holder &m_holder; | |
539 | }; | |
540 | ||
541 | struct move_cloner | |
542 | { | |
543 | move_cloner(node_alloc_holder &holder) | |
544 | : m_holder(holder) | |
545 | {} | |
546 | ||
547 | NodePtr operator()(Node &other) | |
92f5a8d4 TL |
548 | { //Use get_real_data() instead of get_real_data to allow moving const key in [multi]map |
549 | return m_holder.create_node(::boost::move(other.get_real_data())); | |
7c673cae FG |
550 | } |
551 | ||
552 | node_alloc_holder &m_holder; | |
553 | }; | |
554 | ||
7c673cae | 555 | ICont &non_const_icont() const |
92f5a8d4 | 556 | { return const_cast<ICont&>(this->m_icont); } |
7c673cae FG |
557 | |
558 | NodeAlloc &node_alloc() | |
92f5a8d4 | 559 | { return static_cast<NodeAlloc &>(*this); } |
7c673cae FG |
560 | |
561 | const NodeAlloc &node_alloc() const | |
92f5a8d4 | 562 | { return static_cast<const NodeAlloc &>(*this); } |
7c673cae FG |
563 | |
564 | public: | |
565 | ICont &icont() | |
92f5a8d4 | 566 | { return this->m_icont; } |
7c673cae FG |
567 | |
568 | const ICont &icont() const | |
92f5a8d4 TL |
569 | { return this->m_icont; } |
570 | ||
571 | private: | |
572 | //The intrusive container | |
573 | ICont m_icont; | |
7c673cae FG |
574 | }; |
575 | ||
11fdf7f2 | 576 | } //namespace dtl { |
7c673cae FG |
577 | } //namespace container { |
578 | } //namespace boost { | |
579 | ||
580 | #include <boost/container/detail/config_end.hpp> | |
581 | ||
582 | #endif // BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_ |