3 * Copyright 2008 Joaquin M Lopez Munoz.
4 * Distributed under the Boost Software License, Version 1.0.
5 * (See accompanying file LICENSE_1_0.txt or copy at
6 * http://www.boost.org/LICENSE_1_0.txt)
9 #ifndef STABLE_VECTOR_HPP_3A7EB5C0_55BF_11DD_AE16_0800200C9A66
10 #define STABLE_VECTOR_HPP_3A7EB5C0_55BF_11DD_AE16_0800200C9A66
14 #include <boost/mpl/bool.hpp>
15 #include <boost/mpl/not.hpp>
16 #include <boost/noncopyable.hpp>
17 #include <boost/type_traits/is_integral.hpp>
18 #include <boost/interprocess/containers/container/detail/version_type.hpp>
19 #include <boost/interprocess/containers/container/detail/multiallocation_chain.hpp>
20 #include <boost/interprocess/containers/container/detail/utilities.hpp>
21 #include <boost/interprocess/containers/container/detail/algorithms.hpp>
22 #include <boost/pointer_to_other.hpp>
23 #include <boost/get_pointer.hpp>
25 #define STABLE_VECTOR_USE_CONTAINERS_VECTOR
27 #if defined (STABLE_VECTOR_USE_CONTAINERS_VECTOR)
28 #include <boost/interprocess/containers/container/vector.hpp>
31 #endif //STABLE_VECTOR_USE_CONTAINERS_VECTOR
33 //#define STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
35 #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
36 #include <boost/assert.hpp>
39 #ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
41 namespace interprocess
{
44 namespace interprocess_container
{
49 namespace stable_vector_detail
{
51 template<class SmartPtr
>
54 typedef typename
SmartPtr::value_type value_type
;
55 typedef value_type
*pointer
;
56 static pointer
get (const SmartPtr
&smartptr
)
57 { return smartptr
.get();}
61 struct smart_ptr_type
<T
*>
64 typedef value_type
*pointer
;
65 static pointer
get (pointer ptr
)
70 inline typename smart_ptr_type
<Ptr
>::pointer
get_pointer(const Ptr
&ptr
)
71 { return smart_ptr_type
<Ptr
>::get(ptr
); }
74 class clear_on_destroy
77 clear_on_destroy(C
&c
)
78 : c_(c
), do_clear_(true)
82 { do_clear_
= false; }
97 template <class T
, class Difference
= std::ptrdiff_t>
98 class constant_iterator
99 : public std::iterator
100 <std::random_access_iterator_tag
, T
, Difference
, const T
*, const T
&>
102 typedef constant_iterator
<T
, Difference
> this_type
;
105 explicit constant_iterator(const T
&ref
, Difference range_size
)
106 : m_ptr(&ref
), m_num(range_size
){}
110 : m_ptr(0), m_num(0){}
112 constant_iterator
& operator++()
113 { increment(); return *this; }
115 constant_iterator
operator++(int)
117 constant_iterator
result (*this);
122 friend bool operator== (const constant_iterator
& i
, const constant_iterator
& i2
)
123 { return i
.equal(i2
); }
125 friend bool operator!= (const constant_iterator
& i
, const constant_iterator
& i2
)
126 { return !(i
== i2
); }
128 friend bool operator< (const constant_iterator
& i
, const constant_iterator
& i2
)
129 { return i
.less(i2
); }
131 friend bool operator> (const constant_iterator
& i
, const constant_iterator
& i2
)
134 friend bool operator<= (const constant_iterator
& i
, const constant_iterator
& i2
)
135 { return !(i
> i2
); }
137 friend bool operator>= (const constant_iterator
& i
, const constant_iterator
& i2
)
138 { return !(i
< i2
); }
140 friend Difference
operator- (const constant_iterator
& i
, const constant_iterator
& i2
)
141 { return i2
.distance_to(i
); }
144 constant_iterator
& operator+=(Difference off
)
145 { this->advance(off
); return *this; }
147 constant_iterator
operator+(Difference off
) const
149 constant_iterator
other(*this);
154 friend constant_iterator
operator+(Difference off
, const constant_iterator
& right
)
155 { return right
+ off
; }
157 constant_iterator
& operator-=(Difference off
)
158 { this->advance(-off
); return *this; }
160 constant_iterator
operator-(Difference off
) const
161 { return *this + (-off
); }
163 const T
& operator*() const
164 { return dereference(); }
166 const T
* operator->() const
167 { return &(dereference()); }
179 bool equal(const this_type
&other
) const
180 { return m_num
== other
.m_num
; }
182 bool less(const this_type
&other
) const
183 { return other
.m_num
< m_num
; }
185 const T
& dereference() const
188 void advance(Difference n
)
191 Difference
distance_to(const this_type
&other
)const
192 { return m_num
- other
.m_num
; }
195 template<class VoidPtr
>
196 struct node_type_base
198 node_type_base(VoidPtr p)
203 void set_pointer(VoidPtr p
)
209 template<typename VoidPointer
, typename T
>
211 : public node_type_base
<VoidPointer
>
213 #ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
219 #define BOOST_PP_LOCAL_MACRO(n) \
220 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
221 node_type(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
222 : value(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)) \
225 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
226 #include BOOST_PP_LOCAL_ITERATE()
228 #else //#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
234 template<class ...Args
>
235 node_type(Args
&&...args
)
236 : value(boost::interprocess::forward
<Args
>(args
)...)
238 #endif//#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
240 void set_pointer(VoidPointer p
)
241 { node_type_base
<VoidPointer
>::set_pointer(p
); }
246 template<typename T
, typename Value
, typename Pointer
>
248 : public std::iterator
< std::random_access_iterator_tag
249 , const typename
std::iterator_traits
<Pointer
>::value_type
250 , typename
std::iterator_traits
<Pointer
>::difference_type
255 typedef typename
boost::pointer_to_other
256 <Pointer
, void>::type void_ptr
;
257 typedef node_type
<void_ptr
, T
> node_type_t
;
258 typedef typename
boost::pointer_to_other
259 <void_ptr
, node_type_t
>::type node_type_ptr_t
;
260 typedef typename
boost::pointer_to_other
261 <void_ptr
, void_ptr
>::type void_ptr_ptr
;
263 friend class iterator
<T
, const T
, typename
boost::pointer_to_other
<Pointer
, T
>::type
>;
266 typedef std::random_access_iterator_tag iterator_category
;
267 typedef Value value_type
;
268 typedef typename
std::iterator_traits
269 <Pointer
>::difference_type difference_type
;
270 typedef Pointer pointer
;
271 typedef Value
& reference
;
276 explicit iterator(node_type_ptr_t pn
)
280 iterator(const iterator
<T
, T
, typename
boost::pointer_to_other
<Pointer
, T
>::type
>& x
)
285 static node_type_ptr_t
node_ptr_cast(void_ptr p
)
287 using boost::get_pointer
;
288 return node_type_ptr_t(static_cast<node_type_t
*>(stable_vector_detail::get_pointer(p
)));
291 static void_ptr_ptr
void_ptr_ptr_cast(void_ptr p
)
293 using boost::get_pointer
;
294 return void_ptr_ptr(static_cast<void_ptr
*>(stable_vector_detail::get_pointer(p
)));
297 Value
& dereference() const
298 { return pn
->value
; }
299 bool equal(const iterator
& x
) const
302 { pn
= node_ptr_cast(*(void_ptr_ptr_cast(pn
->up
)+1)); }
304 { pn
= node_ptr_cast(*(void_ptr_ptr_cast(pn
->up
)-1)); }
305 void advance(std::ptrdiff_t n
)
306 { pn
= node_ptr_cast(*(void_ptr_ptr_cast(pn
->up
)+n
)); }
307 std::ptrdiff_t distance_to(const iterator
& x
)const
308 { return void_ptr_ptr_cast(x
.pn
->up
) - void_ptr_ptr_cast(pn
->up
); }
311 //Pointer like operators
312 reference
operator*() const { return this->dereference(); }
313 pointer
operator->() const { return pointer(&this->dereference()); }
315 //Increment / Decrement
316 iterator
& operator++()
317 { this->increment(); return *this; }
319 iterator
operator++(int)
320 { iterator
tmp(*this); ++*this; return iterator(tmp
); }
322 iterator
& operator--()
323 { this->decrement(); return *this; }
325 iterator
operator--(int)
326 { iterator
tmp(*this); --*this; return iterator(tmp
); }
328 reference
operator[](difference_type off
) const
335 iterator
& operator+=(difference_type off
)
337 pn
= node_ptr_cast(*(void_ptr_ptr_cast(pn
->up
)+off
));
341 iterator
operator+(difference_type off
) const
348 friend iterator
operator+(difference_type off
, const iterator
& right
)
355 iterator
& operator-=(difference_type off
)
356 { *this += -off
; return *this; }
358 iterator
operator-(difference_type off
) const
365 difference_type
operator-(const iterator
& right
) const
367 void_ptr_ptr p1
= void_ptr_ptr_cast(this->pn
->up
);
368 void_ptr_ptr p2
= void_ptr_ptr_cast(right
.pn
->up
);
372 //Comparison operators
373 bool operator== (const iterator
& r
) const
374 { return pn
== r
.pn
; }
376 bool operator!= (const iterator
& r
) const
377 { return pn
!= r
.pn
; }
379 bool operator< (const iterator
& r
) const
380 { return void_ptr_ptr_cast(pn
->up
) < void_ptr_ptr_cast(r
.pn
->up
); }
382 bool operator<= (const iterator
& r
) const
383 { return void_ptr_ptr_cast(pn
->up
) <= void_ptr_ptr_cast(r
.pn
->up
); }
385 bool operator> (const iterator
& r
) const
386 { return void_ptr_ptr_cast(pn
->up
) > void_ptr_ptr_cast(r
.pn
->up
); }
388 bool operator>= (const iterator
& r
) const
389 { return void_ptr_ptr_cast(pn
->up
) >= void_ptr_ptr_cast(r
.pn
->up
); }
398 template<typename T, typename Value, typename VoidPointer>
399 static typename iterator<T, Value, VoidPointer>::node_type_t* get(const iterator<T,Value,VoidPointer>& it)
401 return stable_vector_detail::get_pointer(it.pn);
406 template<class Allocator
, unsigned int Version
>
407 struct select_multiallocation_chain
409 typedef typename
Allocator::multiallocation_chain type
;
412 template<class Allocator
>
413 struct select_multiallocation_chain
<Allocator
, 1>
415 typedef typename
Allocator::template
416 rebind
<void>::other::pointer void_ptr
;
417 typedef containers_detail::basic_multiallocation_cached_slist
<void_ptr
> multialloc_cached
;
418 typedef containers_detail::basic_multiallocation_cached_counted_slist
419 <multialloc_cached
> multialloc_cached_counted
;
420 typedef boost::interprocess_container::containers_detail::transform_multiallocation_chain
421 <multialloc_cached_counted
, typename
Allocator::value_type
> type
;
424 } //namespace stable_vector_detail
426 #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
428 #define STABLE_VECTOR_CHECK_INVARIANT \
429 invariant_checker BOOST_JOIN(check_invariant_,__LINE__)(*this); \
430 BOOST_JOIN(check_invariant_,__LINE__).touch();
433 #define STABLE_VECTOR_CHECK_INVARIANT
435 #endif //#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
439 template<typename T
,typename Allocator
=std::allocator
<T
> >
442 typedef typename
Allocator::template
443 rebind
<void>::other::pointer void_ptr
;
444 typedef typename
Allocator::template
445 rebind
<void_ptr
>::other::pointer void_ptr_ptr
;
446 typedef stable_vector_detail::node_type
447 <void_ptr
, T
> node_type_t
;
448 typedef typename
Allocator::template
449 rebind
<node_type_t
>::other::pointer node_type_ptr_t
;
450 typedef stable_vector_detail::node_type_base
451 <void_ptr
> node_type_base_t
;
452 typedef typename
Allocator::template
453 rebind
<node_type_base_t
>::other::pointer node_type_base_ptr_t
;
455 #if defined (STABLE_VECTOR_USE_CONTAINERS_VECTOR)
456 ::boost::interprocess_container::
459 #endif //STABLE_VECTOR_USE_CONTAINERS_VECTOR
462 template rebind
<void_ptr
>::other
464 typedef typename
impl_type::iterator impl_iterator
;
465 typedef typename
impl_type::const_iterator const_impl_iterator
;
467 typedef ::boost::interprocess_container::containers_detail::
468 integral_constant
<unsigned, 1> allocator_v1
;
469 typedef ::boost::interprocess_container::containers_detail::
470 integral_constant
<unsigned, 2> allocator_v2
;
471 typedef ::boost::interprocess_container::containers_detail::integral_constant
472 <unsigned, boost::interprocess_container::containers_detail::
473 version
<Allocator
>::value
> alloc_version
;
474 typedef typename
Allocator::
475 template rebind
<node_type_t
>::other node_allocator_type
;
477 node_type_ptr_t
allocate_one()
478 { return this->allocate_one(alloc_version()); }
480 node_type_ptr_t
allocate_one(allocator_v1
)
481 { return get_al().allocate(1); }
483 node_type_ptr_t
allocate_one(allocator_v2
)
484 { return get_al().allocate_one(); }
486 void deallocate_one(node_type_ptr_t p
)
487 { return this->deallocate_one(p
, alloc_version()); }
489 void deallocate_one(node_type_ptr_t p
, allocator_v1
)
490 { get_al().deallocate(p
, 1); }
492 void deallocate_one(node_type_ptr_t p
, allocator_v2
)
493 { get_al().deallocate_one(p
); }
495 friend class stable_vector_detail::clear_on_destroy
<stable_vector
>;
500 typedef typename
Allocator::reference reference
;
501 typedef typename
Allocator::const_reference const_reference
;
502 typedef typename
Allocator::pointer pointer
;
503 typedef typename
Allocator::const_pointer const_pointer
;
504 typedef stable_vector_detail::iterator
505 <T
,T
, pointer
> iterator
;
506 typedef stable_vector_detail::iterator
507 <T
,const T
, const_pointer
> const_iterator
;
508 typedef typename
impl_type::size_type size_type
;
509 typedef typename
iterator::difference_type difference_type
;
510 typedef T value_type
;
511 typedef Allocator allocator_type
;
512 typedef std::reverse_iterator
<iterator
> reverse_iterator
;
513 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
516 static const size_type ExtraPointers
= 3;
517 typedef typename
stable_vector_detail::
518 select_multiallocation_chain
519 < node_allocator_type
520 , alloc_version::value
521 >::type multiallocation_chain
;
524 BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(stable_vector
)
526 // construct/copy/destroy:
527 explicit stable_vector(const Allocator
& al
=Allocator())
528 : internal_data(al
),impl(al
)
530 STABLE_VECTOR_CHECK_INVARIANT
;
533 stable_vector(size_type n
,const T
& t
=T(),const Allocator
& al
=Allocator())
534 : internal_data(al
),impl(al
)
536 stable_vector_detail::clear_on_destroy
<stable_vector
> cod(*this);
537 this->insert(this->cbegin(), n
, t
);
538 STABLE_VECTOR_CHECK_INVARIANT
;
542 template <class InputIterator
>
543 stable_vector(InputIterator first
,InputIterator last
,const Allocator
& al
=Allocator())
544 : internal_data(al
),impl(al
)
546 stable_vector_detail::clear_on_destroy
<stable_vector
> cod(*this);
547 this->insert(this->cbegin(), first
, last
);
548 STABLE_VECTOR_CHECK_INVARIANT
;
552 stable_vector(const stable_vector
& x
)
553 : internal_data(x
.get_al()),impl(x
.get_al())
555 stable_vector_detail::clear_on_destroy
<stable_vector
> cod(*this);
556 this->insert(this->cbegin(), x
.begin(), x
.end());
557 STABLE_VECTOR_CHECK_INVARIANT
;
561 stable_vector(BOOST_INTERPROCESS_RV_REF(stable_vector
) x
)
562 : internal_data(x
.get_al()),impl(x
.get_al())
571 stable_vector
& operator=(const stable_vector
&x
)
573 STABLE_VECTOR_CHECK_INVARIANT
;
575 this->assign(x
.begin(), x
.end());
580 stable_vector
& operator=(BOOST_INTERPROCESS_RV_REF(stable_vector
) x
)
589 template<typename InputIterator
>
590 void assign(InputIterator first
,InputIterator last
)
592 assign_dispatch(first
, last
, boost::is_integral
<InputIterator
>());
595 void assign(size_type n
,const T
& t
)
597 typedef stable_vector_detail::constant_iterator
<value_type
, difference_type
> cvalue_iterator
;
598 return assign_dispatch(cvalue_iterator(t
, n
), cvalue_iterator(), boost::mpl::false_());
601 allocator_type
get_allocator()const {return get_al();}
606 { return (impl
.empty()) ? end(): iterator(node_ptr_cast(impl
.front())) ; }
608 const_iterator
begin()const
609 { return (impl
.empty()) ? cend() : const_iterator(node_ptr_cast(impl
.front())) ; }
611 iterator
end() {return iterator(get_end_node());}
612 const_iterator
end()const {return const_iterator(get_end_node());}
614 reverse_iterator
rbegin() {return reverse_iterator(this->end());}
615 const_reverse_iterator
rbegin()const {return const_reverse_iterator(this->end());}
616 reverse_iterator
rend() {return reverse_iterator(this->begin());}
617 const_reverse_iterator
rend()const {return const_reverse_iterator(this->begin());}
619 const_iterator
cbegin()const {return this->begin();}
620 const_iterator
cend()const {return this->end();}
621 const_reverse_iterator
crbegin()const{return this->rbegin();}
622 const_reverse_iterator
crend()const {return this->rend();}
625 size_type
size() const
626 { return impl
.empty() ? 0 : (impl
.size() - ExtraPointers
); }
628 size_type
max_size() const
629 { return impl
.max_size() - ExtraPointers
; }
631 size_type
capacity() const
633 if(!impl
.capacity()){
637 const size_type num_nodes
= this->impl
.size() + this->internal_data
.pool_size
;
638 const size_type num_buck
= this->impl
.capacity();
639 return (num_nodes
< num_buck
) ? num_nodes
: num_buck
;
644 { return impl
.empty() || impl
.size() == ExtraPointers
; }
646 void resize(size_type n
, const T
& t
)
648 STABLE_VECTOR_CHECK_INVARIANT
;
650 this->insert(this->cend(), n
- this->size(), t
);
651 else if(n
< this->size())
652 this->erase(this->cbegin() + n
, this->cend());
655 void resize(size_type n
)
657 typedef default_construct_iterator
<value_type
, difference_type
> default_iterator
;
658 STABLE_VECTOR_CHECK_INVARIANT
;
660 this->insert(this->cend(), default_iterator(n
- this->size()), default_iterator());
661 else if(n
< this->size())
662 this->erase(this->cbegin() + n
, this->cend());
665 void reserve(size_type n
)
667 STABLE_VECTOR_CHECK_INVARIANT
;
668 if(n
> this->max_size())
669 throw std::bad_alloc();
671 size_type size
= this->size();
672 size_type old_capacity
= this->capacity();
673 if(n
> old_capacity
){
674 this->initialize_end_node(n
);
675 const void * old_ptr
= &impl
[0];
676 impl
.reserve(n
+ ExtraPointers
);
677 bool realloced
= &impl
[0] != old_ptr
;
678 //Fix the pointers for the newly allocated buffer
680 this->align_nodes(impl
.begin(), impl
.begin()+size
+1);
682 //Now fill pool if data is not enough
683 if((n
- size
) > this->internal_data
.pool_size
){
684 this->add_to_pool((n
- size
) - this->internal_data
.pool_size
);
689 void clear_pool(allocator_v1
)
691 if(!impl
.empty() && impl
.back()){
692 void_ptr
&p1
= *(impl
.end()-2);
693 void_ptr
&p2
= impl
.back();
695 multiallocation_chain
holder(p1
, p2
, this->internal_data
.pool_size
);
696 while(!holder
.empty()){
697 node_type_ptr_t n
= holder
.front();
699 this->deallocate_one(n
);
702 this->internal_data
.pool_size
= 0;
706 void clear_pool(allocator_v2
)
709 if(!impl
.empty() && impl
.back()){
710 void_ptr
&p1
= *(impl
.end()-2);
711 void_ptr
&p2
= impl
.back();
712 multiallocation_chain
holder(p1
, p2
, this->internal_data
.pool_size
);
713 get_al().deallocate_individual(boost::interprocess::move(holder
));
715 this->internal_data
.pool_size
= 0;
721 this->clear_pool(alloc_version());
724 void add_to_pool(size_type n
)
726 this->add_to_pool(n
, alloc_version());
729 void add_to_pool(size_type n
, allocator_v1
)
731 size_type remaining
= n
;
733 this->put_in_pool(this->allocate_one());
737 void add_to_pool(size_type n
, allocator_v2
)
739 void_ptr
&p1
= *(impl
.end()-2);
740 void_ptr
&p2
= impl
.back();
741 multiallocation_chain
holder(p1
, p2
, this->internal_data
.pool_size
);
742 BOOST_STATIC_ASSERT((boost::interprocess::is_movable
<multiallocation_chain
>::value
== true));
743 multiallocation_chain
m (get_al().allocate_individual(n
));
744 holder
.splice_after(holder
.before_begin(), m
, m
.before_begin(), m
.last(), n
);
745 this->internal_data
.pool_size
+= n
;
746 std::pair
<void_ptr
, void_ptr
> data(holder
.extract_data());
751 void put_in_pool(node_type_ptr_t p
)
753 void_ptr
&p1
= *(impl
.end()-2);
754 void_ptr
&p2
= impl
.back();
755 multiallocation_chain
holder(p1
, p2
, internal_data
.pool_size
);
756 holder
.push_front(p
);
757 ++this->internal_data
.pool_size
;
758 std::pair
<void_ptr
, void_ptr
> ret(holder
.extract_data());
763 node_type_ptr_t
get_from_pool()
766 return node_type_ptr_t(0);
769 void_ptr
&p1
= *(impl
.end()-2);
770 void_ptr
&p2
= impl
.back();
771 multiallocation_chain
holder(p1
, p2
, internal_data
.pool_size
);
772 node_type_ptr_t ret
= holder
.front();
774 std::pair
<void_ptr
, void_ptr
> data(holder
.extract_data());
777 --this->internal_data
.pool_size
;
784 reference
operator[](size_type n
){return value(impl
[n
]);}
785 const_reference
operator[](size_type n
)const{return value(impl
[n
]);}
787 const_reference
at(size_type n
)const
790 throw std::out_of_range("invalid subscript at stable_vector::at");
791 return operator[](n
);
794 reference
at(size_type n
)
797 throw std::out_of_range("invalid subscript at stable_vector::at");
798 return operator[](n
);
802 { return value(impl
.front()); }
804 const_reference
front()const
805 { return value(impl
.front()); }
808 { return value(*(&impl
.back() - ExtraPointers
)); }
810 const_reference
back()const
811 { return value(*(&impl
.back() - ExtraPointers
)); }
815 void push_back(const T
& t
)
816 { this->insert(end(), t
); }
818 void push_back(BOOST_INTERPROCESS_RV_REF(T
) t
)
819 { this->insert(end(), boost::interprocess::move(t
)); }
822 { this->erase(this->end()-1); }
824 iterator
insert(const_iterator position
, const T
& t
)
826 typedef stable_vector_detail::constant_iterator
<value_type
, difference_type
> cvalue_iterator
;
827 return this->insert_iter(position
, cvalue_iterator(t
, 1), cvalue_iterator(), std::forward_iterator_tag());
830 iterator
insert(const_iterator position
, BOOST_INTERPROCESS_RV_REF(T
) x
)
832 typedef repeat_iterator
<T
, difference_type
> repeat_it
;
833 typedef boost::interprocess::move_iterator
<repeat_it
> repeat_move_it
;
834 //Just call more general insert(pos, size, value) and return iterator
835 size_type pos_n
= position
- cbegin();
836 this->insert(position
837 ,repeat_move_it(repeat_it(x
, 1))
838 ,repeat_move_it(repeat_it()));
839 return iterator(this->begin() + pos_n
);
842 void insert(const_iterator position
, size_type n
, const T
& t
)
844 STABLE_VECTOR_CHECK_INVARIANT
;
845 this->insert_not_iter(position
, n
, t
);
848 template <class InputIterator
>
849 void insert(const_iterator position
,InputIterator first
, InputIterator last
)
851 STABLE_VECTOR_CHECK_INVARIANT
;
852 this->insert_iter(position
,first
,last
,
853 boost::mpl::not_
<boost::is_integral
<InputIterator
> >());
856 #ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
858 //! <b>Effects</b>: Inserts an object of type T constructed with
859 //! std::forward<Args>(args)... in the end of the vector.
861 //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
863 //! <b>Complexity</b>: Amortized constant time.
864 template<class ...Args
>
865 void emplace_back(Args
&&...args
)
867 typedef emplace_functor
<node_type_t
, Args
...> EmplaceFunctor
;
868 typedef emplace_iterator
<node_type_t
, EmplaceFunctor
> EmplaceIterator
;
869 EmplaceFunctor
ef(boost::interprocess::forward
<Args
>(args
)...);
870 this->insert(this->cend(), EmplaceIterator(ef
), EmplaceIterator());
873 //! <b>Requires</b>: position must be a valid iterator of *this.
875 //! <b>Effects</b>: Inserts an object of type T constructed with
876 //! std::forward<Args>(args)... before position
878 //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
880 //! <b>Complexity</b>: If position is end(), amortized constant time
881 //! Linear time otherwise.
882 template<class ...Args
>
883 iterator
emplace(const_iterator position
, Args
&& ...args
)
885 //Just call more general insert(pos, size, value) and return iterator
886 size_type pos_n
= position
- cbegin();
887 typedef emplace_functor
<node_type_t
, Args
...> EmplaceFunctor
;
888 typedef emplace_iterator
<node_type_t
, EmplaceFunctor
> EmplaceIterator
;
889 EmplaceFunctor
ef(boost::interprocess::forward
<Args
>(args
)...);
890 this->insert(position
, EmplaceIterator(ef
), EmplaceIterator());
891 return iterator(this->begin() + pos_n
);
898 typedef emplace_functor
<node_type_t
> EmplaceFunctor
;
899 typedef emplace_iterator
<node_type_t
, EmplaceFunctor
> EmplaceIterator
;
901 this->insert(this->cend(), EmplaceIterator(ef
), EmplaceIterator());
904 iterator
emplace(const_iterator position
)
906 typedef emplace_functor
<node_type_t
> EmplaceFunctor
;
907 typedef emplace_iterator
<node_type_t
, EmplaceFunctor
> EmplaceIterator
;
909 size_type pos_n
= position
- this->cbegin();
910 this->insert(position
, EmplaceIterator(ef
), EmplaceIterator());
911 return iterator(this->begin() + pos_n
);
914 #define BOOST_PP_LOCAL_MACRO(n) \
915 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
916 void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
918 typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
919 <node_type_t, BOOST_PP_ENUM_PARAMS(n, P)> EmplaceFunctor; \
920 typedef emplace_iterator<node_type_t, EmplaceFunctor> EmplaceIterator; \
921 EmplaceFunctor ef(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
922 this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator()); \
925 template<BOOST_PP_ENUM_PARAMS(n, class P)> \
926 iterator emplace(const_iterator pos, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
928 typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
929 <node_type_t, BOOST_PP_ENUM_PARAMS(n, P)> EmplaceFunctor; \
930 typedef emplace_iterator<node_type_t, EmplaceFunctor> EmplaceIterator; \
931 EmplaceFunctor ef(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
932 size_type pos_n = pos - this->cbegin(); \
933 this->insert(pos, EmplaceIterator(ef), EmplaceIterator()); \
934 return iterator(this->begin() + pos_n); \
937 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
938 #include BOOST_PP_LOCAL_ITERATE()
940 #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
942 iterator
erase(const_iterator position
)
944 STABLE_VECTOR_CHECK_INVARIANT
;
945 difference_type d
=position
-this->cbegin();
946 impl_iterator it
=impl
.begin()+d
;
947 this->delete_node(*it
);
949 this->align_nodes(impl
.begin()+d
,get_last_align());
950 return this->begin()+d
;
953 iterator
erase(const_iterator first
, const_iterator last
)
954 { return priv_erase(first
, last
, alloc_version()); }
956 void swap(stable_vector
& x
)
958 STABLE_VECTOR_CHECK_INVARIANT
;
959 this->swap_impl(*this,x
);
963 { this->erase(this->cbegin(),this->cend()); }
968 void insert_iter_prolog(size_type n
, difference_type d
)
970 initialize_end_node(n
);
971 const void* old_ptr
= &impl
[0];
972 //size_type old_capacity = capacity();
973 //size_type old_size = size();
974 impl
.insert(impl
.begin()+d
, n
, 0);
975 bool realloced
= &impl
[0] != old_ptr
;
976 //Fix the pointers for the newly allocated buffer
978 align_nodes(impl
.begin(), impl
.begin()+d
);
982 template<typename InputIterator
>
983 void assign_dispatch(InputIterator first
, InputIterator last
, boost::mpl::false_
)
985 STABLE_VECTOR_CHECK_INVARIANT
;
986 iterator first1
= this->begin();
987 iterator last1
= this->end();
988 for ( ; first1
!= last1
&& first
!= last
; ++first1
, ++first
)
991 this->erase(first1
, last1
);
994 this->insert(last1
, first
, last
);
998 template<typename Integer
>
999 void assign_dispatch(Integer n
, Integer t
, boost::mpl::true_
)
1001 typedef stable_vector_detail::constant_iterator
<value_type
, difference_type
> cvalue_iterator
;
1002 this->assign_dispatch(cvalue_iterator(t
, n
), cvalue_iterator(), boost::mpl::false_());
1005 iterator
priv_erase(const_iterator first
, const_iterator last
, allocator_v1
)
1007 STABLE_VECTOR_CHECK_INVARIANT
;
1008 difference_type d1
= first
- this->cbegin(), d2
= last
- this->cbegin();
1010 impl_iterator
it1(impl
.begin() + d1
), it2(impl
.begin() + d2
);
1011 for(impl_iterator it
= it1
; it
!= it2
; ++it
)
1012 this->delete_node(*it
);
1013 impl
.erase(it1
, it2
);
1014 this->align_nodes(impl
.begin() + d1
, get_last_align());
1016 return iterator(this->begin() + d1
);
1019 impl_iterator
get_last_align()
1021 return impl
.end() - (ExtraPointers
- 1);
1024 const_impl_iterator
get_last_align() const
1026 return impl
.cend() - (ExtraPointers
- 1);
1029 template<class AllocatorVersion
>
1030 iterator
priv_erase(const_iterator first
, const_iterator last
, AllocatorVersion
,
1031 typename
boost::interprocess_container::containers_detail::enable_if_c
1032 <boost::interprocess_container::containers_detail::is_same
<AllocatorVersion
, allocator_v2
>
1033 ::value
>::type
* = 0)
1035 STABLE_VECTOR_CHECK_INVARIANT
;
1036 return priv_erase(first
, last
, allocator_v1());
1039 static node_type_ptr_t
node_ptr_cast(void_ptr p
)
1041 using boost::get_pointer
;
1042 return node_type_ptr_t(static_cast<node_type_t
*>(stable_vector_detail::get_pointer(p
)));
1045 static node_type_base_ptr_t
node_base_ptr_cast(void_ptr p
)
1047 using boost::get_pointer
;
1048 return node_type_base_ptr_t(static_cast<node_type_base_t
*>(stable_vector_detail::get_pointer(p
)));
1051 static value_type
& value(void_ptr p
)
1053 return node_ptr_cast(p
)->value
;
1056 void initialize_end_node(size_type impl_capacity
= 0)
1059 impl
.reserve(impl_capacity
+ ExtraPointers
);
1060 impl
.resize (ExtraPointers
, void_ptr(0));
1061 impl
[0] = &this->internal_data
.end_node
;
1062 this->internal_data
.end_node
.up
= &impl
[0];
1066 void readjust_end_node()
1068 if(!this->impl
.empty()){
1069 void_ptr
&end_node_ref
= *(this->get_last_align()-1);
1070 end_node_ref
= this->get_end_node();
1071 this->internal_data
.end_node
.up
= &end_node_ref
;
1074 this->internal_data
.end_node
.up
= void_ptr(&this->internal_data
.end_node
.up
);
1078 node_type_ptr_t
get_end_node() const
1080 const node_type_base_t
* cp
= &this->internal_data
.end_node
;
1081 node_type_base_t
* p
= const_cast<node_type_base_t
*>(cp
);
1082 return node_ptr_cast(p
);
1085 template<class Iter
>
1086 void_ptr
new_node(void_ptr up
, Iter it
)
1088 node_type_ptr_t p
= this->allocate_one();
1090 boost::interprocess_container::construct_in_place(&*p
, it
);
1094 this->deallocate_one(p
);
1100 void delete_node(void_ptr p
)
1102 node_type_ptr_t
n(node_ptr_cast(p
));
1104 this->put_in_pool(n
);
1107 static void align_nodes(impl_iterator first
,impl_iterator last
)
1110 node_ptr_cast(*first
)->up
= void_ptr(&*first
);
1115 void insert_not_iter(const_iterator position
, size_type n
, const T
& t
)
1117 typedef stable_vector_detail::constant_iterator
<value_type
, difference_type
> cvalue_iterator
;
1118 this->insert_iter(position
, cvalue_iterator(t
, n
), cvalue_iterator(), std::forward_iterator_tag());
1121 template <class InputIterator
>
1122 void insert_iter(const_iterator position
,InputIterator first
,InputIterator last
, boost::mpl::true_
)
1124 typedef typename
std::iterator_traits
<InputIterator
>::iterator_category category
;
1125 this->insert_iter(position
, first
, last
, category());
1128 template <class InputIterator
>
1129 void insert_iter(const_iterator position
,InputIterator first
,InputIterator last
,std::input_iterator_tag
)
1131 for(; first
!=last
; ++first
){
1132 this->insert(position
, *first
);
1136 template <class InputIterator
>
1137 iterator
insert_iter(const_iterator position
, InputIterator first
, InputIterator last
, std::forward_iterator_tag
)
1139 size_type n
= (size_type
)std::distance(first
,last
);
1140 difference_type d
= position
-this->cbegin();
1142 this->insert_iter_prolog(n
, d
);
1143 const impl_iterator
it(impl
.begin() + d
);
1144 this->insert_iter_fwd(it
, first
, last
, n
);
1145 //Fix the pointers for the newly allocated buffer
1146 this->align_nodes(it
+ n
, get_last_align());
1148 return this->begin() + d
;
1151 template <class FwdIterator
>
1152 void insert_iter_fwd_alloc(const impl_iterator it
, FwdIterator first
, FwdIterator last
, difference_type n
, allocator_v1
)
1157 *(it
+ i
) = this->new_node(void_ptr((void*)(&*(it
+ i
))), first
);
1163 impl
.erase(it
+ i
, it
+ n
);
1164 this->align_nodes(it
+ i
, get_last_align());
1169 template <class FwdIterator
>
1170 void insert_iter_fwd_alloc(const impl_iterator it
, FwdIterator first
, FwdIterator last
, difference_type n
, allocator_v2
)
1172 multiallocation_chain
mem(get_al().allocate_individual(n
));
1175 node_type_ptr_t p
= 0;
1177 while(first
!= last
){
1181 boost::interprocess_container::construct_in_place(&*p
, first
);
1182 p
->set_pointer(void_ptr((void*)(&*(it
+ i
))));
1189 get_al().deallocate_one(p
);
1190 get_al().deallocate_many(boost::interprocess::move(mem
));
1191 impl
.erase(it
+i
, it
+n
);
1192 this->align_nodes(it
+i
,get_last_align());
1197 template <class FwdIterator
>
1198 void insert_iter_fwd(const impl_iterator it
, FwdIterator first
, FwdIterator last
, difference_type n
)
1201 node_type_ptr_t p
= 0;
1203 while(first
!= last
){
1204 p
= get_from_pool();
1206 insert_iter_fwd_alloc(it
+i
, first
, last
, n
-i
, alloc_version());
1210 boost::interprocess_container::construct_in_place(&*p
, first
);
1211 p
->set_pointer(void_ptr(&*(it
+i
)));
1219 impl
.erase(it
+i
,it
+n
);
1220 this->align_nodes(it
+i
,get_last_align());
1225 template <class InputIterator
>
1226 void insert_iter(const_iterator position
,InputIterator first
,InputIterator last
, boost::mpl::false_
)
1228 this->insert_not_iter(position
,first
,last
);
1231 static void swap_impl(stable_vector
& x
,stable_vector
& y
)
1234 swap(x
.get_al(),y
.get_al());
1235 swap(x
.impl
,y
.impl
);
1236 swap(x
.internal_data
.pool_size
, y
.internal_data
.pool_size
);
1237 x
.readjust_end_node();
1238 y
.readjust_end_node();
1241 #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
1242 bool invariant()const
1245 return !capacity() && !size();
1246 if(get_end_node() != *(impl
.end() - ExtraPointers
)){
1249 for(const_impl_iterator it
=impl
.begin(),it_end
=get_last_align();it
!=it_end
;++it
){
1250 if(node_ptr_cast(*it
)->up
!= &*it
)
1253 size_type n
= capacity()-size();
1254 const void_ptr
&pool_head
= impl
.back();
1255 size_type num_pool
= 0;
1256 node_type_ptr_t p
= node_ptr_cast(pool_head
);
1261 return n
>= num_pool
;
1264 class invariant_checker
:private boost::noncopyable
1266 const stable_vector
* p
;
1268 invariant_checker(const stable_vector
& v
):p(&v
){}
1269 ~invariant_checker(){BOOST_ASSERT(p
->invariant());}
1275 : node_allocator_type
1277 ebo_holder(const allocator_type
&a
)
1278 : node_allocator_type(a
), pool_size(0), end_node()
1280 end_node
.set_pointer(void_ptr(&end_node
.up
));
1282 size_type pool_size
;
1283 node_type_base_t end_node
;
1286 node_allocator_type
&get_al() { return internal_data
; }
1287 const node_allocator_type
&get_al() const { return internal_data
; }
1293 template <typename T
,typename Allocator
>
1294 bool operator==(const stable_vector
<T
,Allocator
>& x
,const stable_vector
<T
,Allocator
>& y
)
1296 return x
.size()==y
.size()&&std::equal(x
.begin(),x
.end(),y
.begin());
1299 template <typename T
,typename Allocator
>
1300 bool operator< (const stable_vector
<T
,Allocator
>& x
,const stable_vector
<T
,Allocator
>& y
)
1302 return std::lexicographical_compare(x
.begin(),x
.end(),y
.begin(),y
.end());
1305 template <typename T
,typename Allocator
>
1306 bool operator!=(const stable_vector
<T
,Allocator
>& x
,const stable_vector
<T
,Allocator
>& y
)
1311 template <typename T
,typename Allocator
>
1312 bool operator> (const stable_vector
<T
,Allocator
>& x
,const stable_vector
<T
,Allocator
>& y
)
1317 template <typename T
,typename Allocator
>
1318 bool operator>=(const stable_vector
<T
,Allocator
>& x
,const stable_vector
<T
,Allocator
>& y
)
1323 template <typename T
,typename Allocator
>
1324 bool operator<=(const stable_vector
<T
,Allocator
>& x
,const stable_vector
<T
,Allocator
>& y
)
1329 // specialized algorithms:
1331 template <typename T
, typename Allocator
>
1332 void swap(stable_vector
<T
,Allocator
>& x
,stable_vector
<T
,Allocator
>& y
)
1339 #undef STABLE_VECTOR_CHECK_INVARIANT