1 //////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2005-2008. 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)
7 // See http://www.boost.org/libs/container for documentation.
9 //////////////////////////////////////////////////////////////////////////////
11 // This file comes from SGI's stl_tree file. Modified by Ion Gaztanaga 2005.
12 // Renaming, isolating and porting to generic algorithms. Pointer typedef
13 // set to allocator::pointer to allow placing it in shared memory.
15 ///////////////////////////////////////////////////////////////////////////////
19 * Hewlett-Packard Company
21 * Permission to use, copy, modify, distribute and sell this software
22 * and its documentation for any purpose is hereby granted without fee,
23 * provided that the above copyright notice appear in all copies and
24 * that both that copyright notice and this permission notice appear
25 * in supporting documentation. Hewlett-Packard Company makes no
26 * representations about the suitability of this software for any
27 * purpose. It is provided "as is" without express or implied warranty.
31 * Silicon Graphics Computer Systems, Inc.
33 * Permission to use, copy, modify, distribute and sell this software
34 * and its documentation for any purpose is hereby granted without fee,
35 * provided that the above copyright notice appear in all copies and
36 * that both that copyright notice and this permission notice appear
37 * in supporting documentation. Silicon Graphics makes no
38 * representations about the suitability of this software for any
39 * purpose. It is provided "as is" without express or implied warranty.
42 #ifndef BOOST_CONTAINERS_TREE_HPP
43 #define BOOST_CONTAINERS_TREE_HPP
45 #include <boost/interprocess/containers/container/detail/config_begin.hpp>
46 #include <boost/interprocess/containers/container/detail/workaround.hpp>
48 #include <boost/interprocess/detail/move.hpp>
49 #include <boost/pointer_to_other.hpp>
50 #include <boost/type_traits/has_trivial_destructor.hpp>
51 #include <boost/detail/no_exceptions_support.hpp>
52 #include <boost/intrusive/rbtree.hpp>
54 #include <boost/interprocess/containers/container/detail/utilities.hpp>
55 #include <boost/interprocess/containers/container/detail/algorithms.hpp>
56 #include <boost/interprocess/containers/container/detail/node_alloc_holder.hpp>
57 #include <boost/interprocess/containers/container/detail/destroyers.hpp>
58 #include <boost/interprocess/containers/container/detail/pair.hpp>
59 #ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
60 #include <boost/interprocess/containers/container/detail/preprocessor.hpp>
63 #include <utility> //std::pair
68 namespace interprocess_container
{
69 namespace containers_detail
{
71 template<class Key
, class Value
, class KeyCompare
, class KeyOfValue
>
72 struct value_compare_impl
75 typedef Value value_type
;
76 typedef KeyCompare key_compare
;
77 typedef KeyOfValue key_of_value
;
80 value_compare_impl(key_compare kcomp
)
84 const key_compare
&key_comp() const
85 { return static_cast<const key_compare
&>(*this); }
87 key_compare
&key_comp()
88 { return static_cast<key_compare
&>(*this); }
90 template<class A
, class B
>
91 bool operator()(const A
&a
, const B
&b
) const
92 { return key_compare::operator()(KeyOfValue()(a
), KeyOfValue()(b
)); }
95 template<class VoidPointer
>
98 typedef typename
containers_detail::bi::make_set_base_hook
99 < containers_detail::bi::void_pointer
<VoidPointer
>
100 , containers_detail::bi::link_mode
<containers_detail::bi::normal_link
>
101 , containers_detail::bi::optimize_size
<true>
111 template<class T1
, class T2
>
112 struct rbtree_type
< std::pair
<T1
, T2
> >
114 typedef pair
<T1
, T2
> type
;
117 template <class T
, class VoidPointer
>
119 : public rbtree_hook
<VoidPointer
>::type
121 typedef typename rbtree_hook
<VoidPointer
>::type hook_type
;
123 typedef T value_type
;
124 typedef typename rbtree_type
<T
>::type internal_type
;
126 typedef rbtree_node
<T
, VoidPointer
> node_type
;
128 #ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
134 rbtree_node(const rbtree_node
&other
)
135 : m_data(other
.m_data
)
138 #define BOOST_PP_LOCAL_MACRO(n) \
139 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
140 rbtree_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
141 : m_data(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)) \
144 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
145 #include BOOST_PP_LOCAL_ITERATE()
147 #else //#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
153 template<class ...Args
>
154 rbtree_node(Args
&&...args
)
155 : m_data(boost::interprocess::forward
<Args
>(args
)...)
157 #endif//#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
159 rbtree_node
&operator=(const rbtree_node
&other
)
160 { do_assign(other
.m_data
); return *this; }
164 T
* ptr
= reinterpret_cast<T
*>(&this->m_data
);
168 const T
&get_data() const
170 const T
* ptr
= reinterpret_cast<const T
*>(&this->m_data
);
175 internal_type m_data
;
177 template<class A
, class B
>
178 void do_assign(const std::pair
<const A
, B
> &p
)
180 const_cast<A
&>(m_data
.first
) = p
.first
;
181 m_data
.second
= p
.second
;
184 template<class A
, class B
>
185 void do_assign(const pair
<const A
, B
> &p
)
187 const_cast<A
&>(m_data
.first
) = p
.first
;
188 m_data
.second
= p
.second
;
192 void do_assign(const V
&v
)
196 template<class Convertible
>
197 static void construct(node_type
*ptr
, BOOST_INTERPROCESS_FWD_REF(Convertible
) convertible
)
198 { new(ptr
) node_type(boost::interprocess::forward
<Convertible
>(convertible
)); }
201 }//namespace containers_detail {
202 #if !defined(BOOST_HAS_RVALUE_REFS)
203 template<class T
, class VoidPointer
>
204 struct has_own_construct_from_it
205 < boost::interprocess_container::containers_detail::rbtree_node
<T
, VoidPointer
> >
207 static const bool value
= true;
210 namespace containers_detail
{
212 template<class A
, class ValueCompare
>
213 struct intrusive_rbtree_type
215 typedef typename
A::value_type value_type
;
216 typedef typename
boost::pointer_to_other
217 <typename
A::pointer
, void>::type void_pointer
;
218 typedef typename
containers_detail::rbtree_node
219 <value_type
, void_pointer
> node_type
;
220 typedef node_compare
<ValueCompare
, node_type
> node_compare_type
;
221 typedef typename
containers_detail::bi::make_rbtree
223 ,containers_detail::bi::compare
<node_compare_type
>
224 ,containers_detail::bi::base_hook
<typename rbtree_hook
<void_pointer
>::type
>
225 ,containers_detail::bi::constant_time_size
<true>
226 ,containers_detail::bi::size_type
<typename
A::size_type
>
227 >::type container_type
;
228 typedef container_type type
;
231 } //namespace containers_detail {
233 namespace containers_detail
{
235 template <class Key
, class Value
, class KeyOfValue
,
236 class KeyCompare
, class A
>
238 : protected containers_detail::node_alloc_holder
239 <A
, typename
containers_detail::intrusive_rbtree_type
240 <A
, value_compare_impl
<Key
, Value
, KeyCompare
, KeyOfValue
>
244 typedef typename
containers_detail::intrusive_rbtree_type
245 <A
, value_compare_impl
246 <Key
, Value
, KeyCompare
, KeyOfValue
>
248 typedef containers_detail::node_alloc_holder
<A
, Icont
> AllocHolder
;
249 typedef typename
AllocHolder::NodePtr NodePtr
;
250 typedef rbtree
< Key
, Value
, KeyOfValue
251 , KeyCompare
, A
> ThisType
;
252 typedef typename
AllocHolder::NodeAlloc NodeAlloc
;
253 typedef typename
AllocHolder::ValAlloc ValAlloc
;
254 typedef typename
AllocHolder::Node Node
;
255 typedef typename
Icont::iterator iiterator
;
256 typedef typename
Icont::const_iterator iconst_iterator
;
257 typedef containers_detail::allocator_destroyer
<NodeAlloc
> Destroyer
;
258 typedef typename
AllocHolder::allocator_v1 allocator_v1
;
259 typedef typename
AllocHolder::allocator_v2 allocator_v2
;
260 typedef typename
AllocHolder::alloc_version alloc_version
;
262 class RecyclingCloner
;
263 friend class RecyclingCloner
;
265 class RecyclingCloner
268 RecyclingCloner(AllocHolder
&holder
, Icont
&irbtree
)
269 : m_holder(holder
), m_icont(irbtree
)
272 NodePtr
operator()(const Node
&other
) const
274 // if(!m_icont.empty()){
275 if(NodePtr p
= m_icont
.unlink_leftmost_without_rebalance()){
276 //First recycle a node (this can't throw)
277 //NodePtr p = m_icont.unlink_leftmost_without_rebalance();
284 //If there is an exception destroy the whole source
285 m_holder
.destroy_node(p
);
286 while((p
= m_icont
.unlink_leftmost_without_rebalance())){
287 m_holder
.destroy_node(p
);
293 return m_holder
.create_node(other
);
297 AllocHolder
&m_holder
;
302 BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(rbtree
)
304 typedef Key key_type
;
305 typedef Value value_type
;
306 typedef A allocator_type
;
307 typedef KeyCompare key_compare
;
308 typedef value_compare_impl
< Key
, Value
309 , KeyCompare
, KeyOfValue
> value_compare
;
310 typedef typename
A::pointer pointer
;
311 typedef typename
A::const_pointer const_pointer
;
312 typedef typename
A::reference reference
;
313 typedef typename
A::const_reference const_reference
;
314 typedef typename
A::size_type size_type
;
315 typedef typename
A::difference_type difference_type
;
316 typedef difference_type rbtree_difference_type
;
317 typedef pointer rbtree_pointer
;
318 typedef const_pointer rbtree_const_pointer
;
319 typedef reference rbtree_reference
;
320 typedef const_reference rbtree_const_reference
;
321 typedef NodeAlloc stored_allocator_type
;
325 template<class KeyValueCompare
>
326 struct key_node_compare
327 : private KeyValueCompare
329 key_node_compare(KeyValueCompare comp
)
330 : KeyValueCompare(comp
)
333 template<class KeyType
>
334 bool operator()(const Node
&n
, const KeyType
&k
) const
335 { return KeyValueCompare::operator()(n
.get_data(), k
); }
337 template<class KeyType
>
338 bool operator()(const KeyType
&k
, const Node
&n
) const
339 { return KeyValueCompare::operator()(k
, n
.get_data()); }
342 typedef key_node_compare
<value_compare
> KeyNodeCompare
;
345 //rbtree const_iterator
347 : public std::iterator
348 < std::bidirectional_iterator_tag
349 , value_type
, rbtree_difference_type
350 , rbtree_const_pointer
, rbtree_const_reference
>
353 typedef typename
Icont::iterator iiterator
;
355 explicit const_iterator(iiterator it
) : m_it(it
){}
356 void prot_incr() { ++m_it
; }
357 void prot_decr() { --m_it
; }
361 { return this->m_it
; }
364 friend class rbtree
<Key
, Value
, KeyOfValue
, KeyCompare
, A
>;
365 typedef rbtree_difference_type difference_type
;
372 //Pointer like operators
373 const_reference
operator*() const
374 { return m_it
->get_data(); }
376 const_pointer
operator->() const
377 { return const_pointer(&m_it
->get_data()); }
379 //Increment / Decrement
380 const_iterator
& operator++()
381 { prot_incr(); return *this; }
383 const_iterator
operator++(int)
384 { iiterator tmp
= m_it
; ++*this; return const_iterator(tmp
); }
386 const_iterator
& operator--()
387 { prot_decr(); return *this; }
389 const_iterator
operator--(int)
390 { iiterator tmp
= m_it
; --*this; return const_iterator(tmp
); }
392 //Comparison operators
393 bool operator== (const const_iterator
& r
) const
394 { return m_it
== r
.m_it
; }
396 bool operator!= (const const_iterator
& r
) const
397 { return m_it
!= r
.m_it
; }
401 class iterator
: public const_iterator
404 explicit iterator(iiterator it
)
409 { return this->m_it
; }
412 friend class rbtree
<Key
, Value
, KeyOfValue
, KeyCompare
, A
>;
413 typedef rbtree_pointer pointer
;
414 typedef rbtree_reference reference
;
419 //Pointer like operators
420 reference
operator*() const { return this->m_it
->get_data(); }
421 pointer
operator->() const { return pointer(&this->m_it
->get_data()); }
423 //Increment / Decrement
424 iterator
& operator++()
425 { this->prot_incr(); return *this; }
427 iterator
operator++(int)
428 { iiterator tmp
= this->m_it
; ++*this; return iterator(tmp
); }
430 iterator
& operator--()
431 { this->prot_decr(); return *this; }
433 iterator
operator--(int)
434 { iterator tmp
= *this; --*this; return tmp
; }
437 typedef std::reverse_iterator
<iterator
> reverse_iterator
;
438 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
440 rbtree(const key_compare
& comp
= key_compare(),
441 const allocator_type
& a
= allocator_type())
442 : AllocHolder(a
, comp
)
445 template <class InputIterator
>
446 rbtree(InputIterator first
, InputIterator last
, const key_compare
& comp
,
447 const allocator_type
& a
, bool unique_insertion
)
448 : AllocHolder(a
, comp
)
450 typedef typename
std::iterator_traits
<InputIterator
>::iterator_category ItCat
;
451 priv_create_and_insert_nodes(first
, last
, unique_insertion
, alloc_version(), ItCat());
454 rbtree(const rbtree
& x
)
455 : AllocHolder(x
, x
.key_comp())
457 this->icont().clone_from
458 (x
.icont(), typename
AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
461 rbtree(BOOST_INTERPROCESS_RV_REF(rbtree
) x
)
462 : AllocHolder(x
, x
.key_comp())
466 {} //AllocHolder clears the tree
468 rbtree
& operator=(const rbtree
& x
)
471 //Transfer all the nodes to a temporary tree
472 //If anything goes wrong, all the nodes will be destroyed
474 Icont
other_tree(this->icont().value_comp());
475 other_tree
.swap(this->icont());
477 //Now recreate the source tree reusing nodes stored by other_tree
478 this->icont().clone_from
480 , RecyclingCloner(*this, other_tree
)
481 //, AllocHolder::cloner(*this)
482 , Destroyer(this->node_alloc()));
484 //If there are remaining nodes, destroy them
486 while((p
= other_tree
.unlink_leftmost_without_rebalance())){
487 AllocHolder::destroy_node(p
);
493 rbtree
& operator=(BOOST_INTERPROCESS_RV_REF(rbtree
) mx
)
494 { this->clear(); this->swap(mx
); return *this; }
498 value_compare
value_comp() const
499 { return this->icont().value_comp().value_comp(); }
501 key_compare
key_comp() const
502 { return this->icont().value_comp().value_comp().key_comp(); }
504 allocator_type
get_allocator() const
505 { return allocator_type(this->node_alloc()); }
507 const stored_allocator_type
&get_stored_allocator() const
508 { return this->node_alloc(); }
510 stored_allocator_type
&get_stored_allocator()
511 { return this->node_alloc(); }
514 { return iterator(this->icont().begin()); }
516 const_iterator
begin() const
517 { return this->cbegin(); }
520 { return iterator(this->icont().end()); }
522 const_iterator
end() const
523 { return this->cend(); }
525 reverse_iterator
rbegin()
526 { return reverse_iterator(end()); }
528 const_reverse_iterator
rbegin() const
529 { return this->crbegin(); }
531 reverse_iterator
rend()
532 { return reverse_iterator(begin()); }
534 const_reverse_iterator
rend() const
535 { return this->crend(); }
537 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
539 //! <b>Throws</b>: Nothing.
541 //! <b>Complexity</b>: Constant.
542 const_iterator
cbegin() const
543 { return const_iterator(this->non_const_icont().begin()); }
545 //! <b>Effects</b>: Returns a const_iterator to the end of the container.
547 //! <b>Throws</b>: Nothing.
549 //! <b>Complexity</b>: Constant.
550 const_iterator
cend() const
551 { return const_iterator(this->non_const_icont().end()); }
553 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
554 //! of the reversed container.
556 //! <b>Throws</b>: Nothing.
558 //! <b>Complexity</b>: Constant.
559 const_reverse_iterator
crbegin() const
560 { return const_reverse_iterator(cend()); }
562 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
563 //! of the reversed container.
565 //! <b>Throws</b>: Nothing.
567 //! <b>Complexity</b>: Constant.
568 const_reverse_iterator
crend() const
569 { return const_reverse_iterator(cbegin()); }
572 { return !this->size(); }
574 size_type
size() const
575 { return this->icont().size(); }
577 size_type
max_size() const
578 { return AllocHolder::max_size(); }
580 void swap(ThisType
& x
)
581 { AllocHolder::swap(x
); }
585 typedef typename
Icont::insert_commit_data insert_commit_data
;
588 std::pair
<iterator
,bool> insert_unique_check
589 (const key_type
& key
, insert_commit_data
&data
)
591 std::pair
<iiterator
, bool> ret
=
592 this->icont().insert_unique_check(key
, KeyNodeCompare(value_comp()), data
);
593 return std::pair
<iterator
, bool>(iterator(ret
.first
), ret
.second
);
596 std::pair
<iterator
,bool> insert_unique_check
597 (const_iterator hint
, const key_type
& key
, insert_commit_data
&data
)
599 std::pair
<iiterator
, bool> ret
=
600 this->icont().insert_unique_check(hint
.get(), key
, KeyNodeCompare(value_comp()), data
);
601 return std::pair
<iterator
, bool>(iterator(ret
.first
), ret
.second
);
604 iterator
insert_unique_commit(const value_type
& v
, insert_commit_data
&data
)
606 NodePtr tmp
= AllocHolder::create_node(v
);
607 iiterator
it(this->icont().insert_unique_commit(*tmp
, data
));
611 template<class MovableConvertible
>
612 iterator insert_unique_commit
613 (BOOST_INTERPROCESS_FWD_REF(MovableConvertible
) mv
, insert_commit_data
&data
)
615 NodePtr tmp
= AllocHolder::create_node(boost::interprocess::forward
<MovableConvertible
>(mv
));
616 iiterator
it(this->icont().insert_unique_commit(*tmp
, data
));
620 std::pair
<iterator
,bool> insert_unique(const value_type
& v
)
622 insert_commit_data data
;
623 std::pair
<iterator
,bool> ret
=
624 this->insert_unique_check(KeyOfValue()(v
), data
);
627 return std::pair
<iterator
,bool>
628 (this->insert_unique_commit(v
, data
), true);
631 template<class MovableConvertible
>
632 std::pair
<iterator
,bool> insert_unique(BOOST_INTERPROCESS_FWD_REF(MovableConvertible
) mv
)
634 insert_commit_data data
;
635 std::pair
<iterator
,bool> ret
=
636 this->insert_unique_check(KeyOfValue()(mv
), data
);
639 return std::pair
<iterator
,bool>
640 (this->insert_unique_commit(boost::interprocess::forward
<MovableConvertible
>(mv
), data
), true);
644 iterator
emplace_unique_impl(NodePtr p
)
646 value_type
&v
= p
->get_data();
647 insert_commit_data data
;
648 std::pair
<iterator
,bool> ret
=
649 this->insert_unique_check(KeyOfValue()(v
), data
);
651 Destroyer(this->node_alloc())(p
);
654 return iterator(iiterator(this->icont().insert_unique_commit(*p
, data
)));
657 iterator
emplace_unique_hint_impl(const_iterator hint
, NodePtr p
)
659 value_type
&v
= p
->get_data();
660 insert_commit_data data
;
661 std::pair
<iterator
,bool> ret
=
662 this->insert_unique_check(hint
, KeyOfValue()(v
), data
);
664 Destroyer(this->node_alloc())(p
);
667 return iterator(iiterator(this->icont().insert_unique_commit(*p
, data
)));
672 #ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
674 template <class... Args
>
675 iterator
emplace_unique(Args
&&... args
)
676 { return this->emplace_unique_impl(AllocHolder::create_node(boost::interprocess::forward
<Args
>(args
)...)); }
678 template <class... Args
>
679 iterator
emplace_hint_unique(const_iterator hint
, Args
&&... args
)
680 { return this->emplace_unique_hint_impl(hint
, AllocHolder::create_node(boost::interprocess::forward
<Args
>(args
)...)); }
682 template <class... Args
>
683 iterator
emplace_equal(Args
&&... args
)
685 NodePtr
p(AllocHolder::create_node(boost::interprocess::forward
<Args
>(args
)...));
686 return iterator(this->icont().insert_equal(this->icont().end(), *p
));
689 template <class... Args
>
690 iterator
emplace_hint_equal(const_iterator hint
, Args
&&... args
)
692 NodePtr
p(AllocHolder::create_node(boost::interprocess::forward
<Args
>(args
)...));
693 return iterator(this->icont().insert_equal(hint
.get(), *p
));
696 #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
698 iterator
emplace_unique()
699 { return this->emplace_unique_impl(AllocHolder::create_node()); }
701 iterator
emplace_hint_unique(const_iterator hint
)
702 { return this->emplace_unique_hint_impl(hint
, AllocHolder::create_node()); }
704 iterator
emplace_equal()
706 NodePtr
p(AllocHolder::create_node());
707 return iterator(this->icont().insert_equal(this->icont().end(), *p
));
710 iterator
emplace_hint_equal(const_iterator hint
)
712 NodePtr
p(AllocHolder::create_node());
713 return iterator(this->icont().insert_equal(hint
.get(), *p
));
716 #define BOOST_PP_LOCAL_MACRO(n) \
717 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
718 iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
720 return this->emplace_unique_impl \
721 (AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
724 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
725 iterator emplace_hint_unique(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
727 return this->emplace_unique_hint_impl \
728 (hint, AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
731 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
732 iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
734 NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
735 return iterator(this->icont().insert_equal(this->icont().end(), *p)); \
738 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
739 iterator emplace_hint_equal(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
741 NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
742 return iterator(this->icont().insert_equal(hint.get(), *p)); \
745 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
746 #include BOOST_PP_LOCAL_ITERATE()
748 #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
750 iterator
insert_unique(const_iterator hint
, const value_type
& v
)
752 insert_commit_data data
;
753 std::pair
<iterator
,bool> ret
=
754 this->insert_unique_check(hint
, KeyOfValue()(v
), data
);
757 return this->insert_unique_commit(v
, data
);
760 template<class MovableConvertible
>
761 iterator
insert_unique(const_iterator hint
, BOOST_INTERPROCESS_FWD_REF(MovableConvertible
) mv
)
763 insert_commit_data data
;
764 std::pair
<iterator
,bool> ret
=
765 this->insert_unique_check(hint
, KeyOfValue()(mv
), data
);
768 return this->insert_unique_commit(boost::interprocess::forward
<MovableConvertible
>(mv
), data
);
771 template <class InputIterator
>
772 void insert_unique(InputIterator first
, InputIterator last
)
775 //Insert with end hint, to achieve linear
776 //complexity if [first, last) is ordered
777 const_iterator
end(this->end());
778 for( ; first
!= last
; ++first
)
779 this->insert_unique(end
, *first
);
782 for( ; first
!= last
; ++first
)
783 this->insert_unique(*first
);
787 iterator
insert_equal(const value_type
& v
)
789 NodePtr
p(AllocHolder::create_node(v
));
790 return iterator(this->icont().insert_equal(this->icont().end(), *p
));
793 template<class MovableConvertible
>
794 iterator
insert_equal(BOOST_INTERPROCESS_FWD_REF(MovableConvertible
) mv
)
796 NodePtr
p(AllocHolder::create_node(boost::interprocess::forward
<MovableConvertible
>(mv
)));
797 return iterator(this->icont().insert_equal(this->icont().end(), *p
));
800 iterator
insert_equal(const_iterator hint
, const value_type
& v
)
802 NodePtr
p(AllocHolder::create_node(v
));
803 return iterator(this->icont().insert_equal(hint
.get(), *p
));
806 template<class MovableConvertible
>
807 iterator
insert_equal(const_iterator hint
, BOOST_INTERPROCESS_FWD_REF(MovableConvertible
) mv
)
809 NodePtr
p(AllocHolder::create_node(boost::interprocess::forward
<MovableConvertible
>(mv
)));
810 return iterator(this->icont().insert_equal(hint
.get(), *p
));
813 template <class InputIterator
>
814 void insert_equal(InputIterator first
, InputIterator last
)
816 //Insert with end hint, to achieve linear
817 //complexity if [first, last) is ordered
818 const_iterator
end(this->cend());
819 for( ; first
!= last
; ++first
)
820 this->insert_equal(end
, *first
);
823 iterator
erase(const_iterator position
)
824 { return iterator(this->icont().erase_and_dispose(position
.get(), Destroyer(this->node_alloc()))); }
826 size_type
erase(const key_type
& k
)
827 { return AllocHolder::erase_key(k
, KeyNodeCompare(value_comp()), alloc_version()); }
829 iterator
erase(const_iterator first
, const_iterator last
)
830 { return iterator(AllocHolder::erase_range(first
.get(), last
.get(), alloc_version())); }
833 { AllocHolder::clear(alloc_version()); }
836 iterator
find(const key_type
& k
)
837 { return iterator(this->icont().find(k
, KeyNodeCompare(value_comp()))); }
839 const_iterator
find(const key_type
& k
) const
840 { return const_iterator(this->non_const_icont().find(k
, KeyNodeCompare(value_comp()))); }
842 size_type
count(const key_type
& k
) const
843 { return size_type(this->icont().count(k
, KeyNodeCompare(value_comp()))); }
845 iterator
lower_bound(const key_type
& k
)
846 { return iterator(this->icont().lower_bound(k
, KeyNodeCompare(value_comp()))); }
848 const_iterator
lower_bound(const key_type
& k
) const
849 { return const_iterator(this->non_const_icont().lower_bound(k
, KeyNodeCompare(value_comp()))); }
851 iterator
upper_bound(const key_type
& k
)
852 { return iterator(this->icont().upper_bound(k
, KeyNodeCompare(value_comp()))); }
854 const_iterator
upper_bound(const key_type
& k
) const
855 { return const_iterator(this->non_const_icont().upper_bound(k
, KeyNodeCompare(value_comp()))); }
857 std::pair
<iterator
,iterator
> equal_range(const key_type
& k
)
859 std::pair
<iiterator
, iiterator
> ret
=
860 this->icont().equal_range(k
, KeyNodeCompare(value_comp()));
861 return std::pair
<iterator
,iterator
>(iterator(ret
.first
), iterator(ret
.second
));
864 std::pair
<const_iterator
, const_iterator
> equal_range(const key_type
& k
) const
866 std::pair
<iiterator
, iiterator
> ret
=
867 this->non_const_icont().equal_range(k
, KeyNodeCompare(value_comp()));
868 return std::pair
<const_iterator
,const_iterator
>
869 (const_iterator(ret
.first
), const_iterator(ret
.second
));
873 //Iterator range version
874 template<class InpIterator
>
875 void priv_create_and_insert_nodes
876 (InpIterator beg
, InpIterator end
, bool unique
)
878 typedef typename
std::iterator_traits
<InpIterator
>::iterator_category ItCat
;
879 priv_create_and_insert_nodes(beg
, end
, unique
, alloc_version(), ItCat());
882 template<class InpIterator
>
883 void priv_create_and_insert_nodes
884 (InpIterator beg
, InpIterator end
, bool unique
, allocator_v1
, std::input_iterator_tag
)
887 for (; beg
!= end
; ++beg
){
888 this->insert_unique(*beg
);
892 for (; beg
!= end
; ++beg
){
893 this->insert_equal(*beg
);
898 template<class InpIterator
>
899 void priv_create_and_insert_nodes
900 (InpIterator beg
, InpIterator end
, bool unique
, allocator_v2
, std::input_iterator_tag
)
901 { //Just forward to the default one
902 priv_create_and_insert_nodes(beg
, end
, unique
, allocator_v1(), std::input_iterator_tag());
905 class insertion_functor
;
906 friend class insertion_functor
;
908 class insertion_functor
913 insertion_functor(Icont
&icont
)
917 void operator()(Node
&n
)
918 { this->icont_
.insert_equal(this->icont_
.cend(), n
); }
922 template<class FwdIterator
>
923 void priv_create_and_insert_nodes
924 (FwdIterator beg
, FwdIterator end
, bool unique
, allocator_v2
, std::forward_iterator_tag
)
928 priv_create_and_insert_nodes(beg
, end
, unique
, allocator_v2(), std::input_iterator_tag());
931 //Optimized allocation and construction
932 this->allocate_many_and_construct
933 (beg
, std::distance(beg
, end
), insertion_functor(this->icont()));
939 template <class Key
, class Value
, class KeyOfValue
,
940 class KeyCompare
, class A
>
942 operator==(const rbtree
<Key
,Value
,KeyOfValue
,KeyCompare
,A
>& x
,
943 const rbtree
<Key
,Value
,KeyOfValue
,KeyCompare
,A
>& y
)
945 return x
.size() == y
.size() &&
946 std::equal(x
.begin(), x
.end(), y
.begin());
949 template <class Key
, class Value
, class KeyOfValue
,
950 class KeyCompare
, class A
>
952 operator<(const rbtree
<Key
,Value
,KeyOfValue
,KeyCompare
,A
>& x
,
953 const rbtree
<Key
,Value
,KeyOfValue
,KeyCompare
,A
>& y
)
955 return std::lexicographical_compare(x
.begin(), x
.end(),
959 template <class Key
, class Value
, class KeyOfValue
,
960 class KeyCompare
, class A
>
962 operator!=(const rbtree
<Key
,Value
,KeyOfValue
,KeyCompare
,A
>& x
,
963 const rbtree
<Key
,Value
,KeyOfValue
,KeyCompare
,A
>& y
) {
967 template <class Key
, class Value
, class KeyOfValue
,
968 class KeyCompare
, class A
>
970 operator>(const rbtree
<Key
,Value
,KeyOfValue
,KeyCompare
,A
>& x
,
971 const rbtree
<Key
,Value
,KeyOfValue
,KeyCompare
,A
>& y
) {
975 template <class Key
, class Value
, class KeyOfValue
,
976 class KeyCompare
, class A
>
978 operator<=(const rbtree
<Key
,Value
,KeyOfValue
,KeyCompare
,A
>& x
,
979 const rbtree
<Key
,Value
,KeyOfValue
,KeyCompare
,A
>& y
) {
983 template <class Key
, class Value
, class KeyOfValue
,
984 class KeyCompare
, class A
>
986 operator>=(const rbtree
<Key
,Value
,KeyOfValue
,KeyCompare
,A
>& x
,
987 const rbtree
<Key
,Value
,KeyOfValue
,KeyCompare
,A
>& y
) {
992 template <class Key
, class Value
, class KeyOfValue
,
993 class KeyCompare
, class A
>
995 swap(rbtree
<Key
,Value
,KeyOfValue
,KeyCompare
,A
>& x
,
996 rbtree
<Key
,Value
,KeyOfValue
,KeyCompare
,A
>& y
)
1001 } //namespace containers_detail {
1002 } //namespace interprocess_container {
1004 namespace interprocess
{
1006 //!has_trivial_destructor_after_move<> == true_type
1007 //!specialization for optimizations
1008 template <class K
, class V
, class KOV
,
1010 struct has_trivial_destructor_after_move
1011 <boost::interprocess_container::containers_detail::rbtree
<K
, V
, KOV
, C
, A
> >
1013 static const bool value
= has_trivial_destructor
<A
>::value
&& has_trivial_destructor
<C
>::value
;
1016 } //namespace interprocess {
1018 } //namespace boost {
1020 #include <boost/interprocess/containers/container/detail/config_end.hpp>
1022 #endif //BOOST_CONTAINERS_TREE_HPP