mirror of
https://github.com/boostorg/container.git
synced 2025-08-01 21:44:27 +02:00
Clean-up insertion code and speed upt single value insertion for proxies having that trait.
This commit is contained in:
@@ -1514,7 +1514,7 @@ private:
|
|||||||
BOOST_CONTAINER_FORCEINLINE void reserve(size_type new_cap)
|
BOOST_CONTAINER_FORCEINLINE void reserve(size_type new_cap)
|
||||||
{
|
{
|
||||||
if (this->capacity() < new_cap){
|
if (this->capacity() < new_cap){
|
||||||
this->priv_reserve_no_capacity(new_cap, alloc_version());
|
this->priv_move_to_new_buffer(new_cap, alloc_version());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1762,9 +1762,9 @@ private:
|
|||||||
return *p;
|
return *p;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
typedef dtl::insert_emplace_proxy<allocator_type, T*, Args...> type;
|
typedef dtl::insert_emplace_proxy<allocator_type, T*, Args...> proxy_t;
|
||||||
return *this->priv_forward_range_insert_no_capacity
|
return *this->priv_insert_forward_range_no_capacity
|
||||||
(this->back_ptr(), 1, type(::boost::forward<Args>(args)...), alloc_version());
|
(this->back_ptr(), 1, proxy_t(::boost::forward<Args>(args)...), alloc_version());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1803,9 +1803,9 @@ private:
|
|||||||
{
|
{
|
||||||
BOOST_ASSERT(this->priv_in_range_or_end(position));
|
BOOST_ASSERT(this->priv_in_range_or_end(position));
|
||||||
//Just call more general insert(pos, size, value) and return iterator
|
//Just call more general insert(pos, size, value) and return iterator
|
||||||
typedef dtl::insert_emplace_proxy<allocator_type, T*, Args...> type;
|
typedef dtl::insert_emplace_proxy<allocator_type, T*, Args...> proxy_t;
|
||||||
return this->priv_forward_range_insert( vector_iterator_get_ptr(position), 1
|
return this->priv_insert_forward_range( vector_iterator_get_ptr(position), 1
|
||||||
, type(::boost::forward<Args>(args)...));
|
, proxy_t(::boost::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||||
@@ -1822,9 +1822,9 @@ private:
|
|||||||
return *p;\
|
return *p;\
|
||||||
}\
|
}\
|
||||||
else{\
|
else{\
|
||||||
typedef dtl::insert_emplace_proxy_arg##N<allocator_type, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
|
typedef dtl::insert_emplace_proxy_arg##N<allocator_type, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> proxy_t;\
|
||||||
return *this->priv_forward_range_insert_no_capacity\
|
return *this->priv_insert_forward_range_no_capacity\
|
||||||
( this->back_ptr(), 1, type(BOOST_MOVE_FWD##N), alloc_version());\
|
( this->back_ptr(), 1, proxy_t(BOOST_MOVE_FWD##N), alloc_version());\
|
||||||
}\
|
}\
|
||||||
}\
|
}\
|
||||||
\
|
\
|
||||||
@@ -1844,8 +1844,8 @@ private:
|
|||||||
BOOST_CONTAINER_FORCEINLINE iterator emplace(const_iterator pos BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
BOOST_CONTAINER_FORCEINLINE iterator emplace(const_iterator pos BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||||
{\
|
{\
|
||||||
BOOST_ASSERT(this->priv_in_range_or_end(pos));\
|
BOOST_ASSERT(this->priv_in_range_or_end(pos));\
|
||||||
typedef dtl::insert_emplace_proxy_arg##N<allocator_type, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
|
typedef dtl::insert_emplace_proxy_arg##N<allocator_type, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> proxy_t;\
|
||||||
return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), 1, type(BOOST_MOVE_FWD##N));\
|
return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), 1, proxy_t(BOOST_MOVE_FWD##N));\
|
||||||
}\
|
}\
|
||||||
//
|
//
|
||||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_VECTOR_EMPLACE_CODE)
|
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_VECTOR_EMPLACE_CODE)
|
||||||
@@ -1911,7 +1911,7 @@ private:
|
|||||||
{
|
{
|
||||||
BOOST_ASSERT(this->priv_in_range_or_end(p));
|
BOOST_ASSERT(this->priv_in_range_or_end(p));
|
||||||
dtl::insert_n_copies_proxy<allocator_type, T*> proxy(x);
|
dtl::insert_n_copies_proxy<allocator_type, T*> proxy(x);
|
||||||
return this->priv_forward_range_insert(vector_iterator_get_ptr(p), n, proxy);
|
return this->priv_insert_forward_range(vector_iterator_get_ptr(p), n, proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! <b>Requires</b>: p must be a valid iterator of *this.
|
//! <b>Requires</b>: p must be a valid iterator of *this.
|
||||||
@@ -1957,7 +1957,7 @@ private:
|
|||||||
{
|
{
|
||||||
BOOST_ASSERT(this->priv_in_range_or_end(pos));
|
BOOST_ASSERT(this->priv_in_range_or_end(pos));
|
||||||
dtl::insert_range_proxy<allocator_type, FwdIt, T*> proxy(first);
|
dtl::insert_range_proxy<allocator_type, FwdIt, T*> proxy(first);
|
||||||
return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), boost::container::iterator_distance(first, last), proxy);
|
return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), boost::container::iterator_distance(first, last), proxy);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1985,7 +1985,7 @@ private:
|
|||||||
num == static_cast<size_type>(boost::container::iterator_distance(first, last)));
|
num == static_cast<size_type>(boost::container::iterator_distance(first, last)));
|
||||||
(void)last;
|
(void)last;
|
||||||
dtl::insert_range_proxy<allocator_type, InIt, T*> proxy(first);
|
dtl::insert_range_proxy<allocator_type, InIt, T*> proxy(first);
|
||||||
return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), num, proxy);
|
return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), num, proxy);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2504,7 +2504,7 @@ private:
|
|||||||
dtl::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), dtl::bool_<propagate_alloc>());
|
dtl::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), dtl::bool_<propagate_alloc>());
|
||||||
}
|
}
|
||||||
|
|
||||||
void priv_reserve_no_capacity(size_type, version_0)
|
BOOST_CONTAINER_FORCEINLINE void priv_move_to_new_buffer(size_type, version_0)
|
||||||
{ alloc_holder_t::on_capacity_overflow(); }
|
{ alloc_holder_t::on_capacity_overflow(); }
|
||||||
|
|
||||||
BOOST_CONTAINER_FORCEINLINE dtl::insert_range_proxy<allocator_type, boost::move_iterator<T*>, T*> priv_dummy_empty_proxy()
|
BOOST_CONTAINER_FORCEINLINE dtl::insert_range_proxy<allocator_type, boost::move_iterator<T*>, T*> priv_dummy_empty_proxy()
|
||||||
@@ -2513,7 +2513,7 @@ private:
|
|||||||
(::boost::make_move_iterator((T *)0));
|
(::boost::make_move_iterator((T *)0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void priv_reserve_no_capacity(size_type new_cap, version_1)
|
BOOST_CONTAINER_FORCEINLINE void priv_move_to_new_buffer(size_type new_cap, version_1)
|
||||||
{
|
{
|
||||||
//There is not enough memory, allocate a new buffer
|
//There is not enough memory, allocate a new buffer
|
||||||
//Pass the hint so that allocators can take advantage of this.
|
//Pass the hint so that allocators can take advantage of this.
|
||||||
@@ -2522,11 +2522,11 @@ private:
|
|||||||
++this->num_alloc;
|
++this->num_alloc;
|
||||||
#endif
|
#endif
|
||||||
//We will reuse insert code, so create a dummy input iterator
|
//We will reuse insert code, so create a dummy input iterator
|
||||||
this->priv_forward_range_insert_new_allocation
|
this->priv_insert_forward_range_new_allocation
|
||||||
( boost::movelib::to_raw_pointer(p), new_cap, this->priv_raw_end(), 0, this->priv_dummy_empty_proxy());
|
( boost::movelib::to_raw_pointer(p), new_cap, this->priv_raw_end(), 0, this->priv_dummy_empty_proxy());
|
||||||
}
|
}
|
||||||
|
|
||||||
void priv_reserve_no_capacity(size_type new_cap, version_2)
|
void priv_move_to_new_buffer(size_type new_cap, version_2)
|
||||||
{
|
{
|
||||||
//There is not enough memory, allocate a new
|
//There is not enough memory, allocate a new
|
||||||
//buffer or expand the old one.
|
//buffer or expand the old one.
|
||||||
@@ -2550,14 +2550,14 @@ private:
|
|||||||
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
||||||
++this->num_expand_bwd;
|
++this->num_expand_bwd;
|
||||||
#endif
|
#endif
|
||||||
this->priv_forward_range_insert_expand_backwards
|
this->priv_insert_forward_range_expand_backwards
|
||||||
( new_mem , real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
|
( new_mem , real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
|
||||||
}
|
}
|
||||||
else{ //New buffer
|
else{ //New buffer
|
||||||
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
||||||
++this->num_alloc;
|
++this->num_alloc;
|
||||||
#endif
|
#endif
|
||||||
this->priv_forward_range_insert_new_allocation
|
this->priv_insert_forward_range_new_allocation
|
||||||
( new_mem, real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
|
( new_mem, real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2600,19 +2600,17 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class U>
|
template<class U>
|
||||||
iterator priv_insert(const const_iterator &p, BOOST_FWD_REF(U) x)
|
BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const const_iterator &p, BOOST_FWD_REF(U) u)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(this->priv_in_range_or_end(p));
|
BOOST_ASSERT(this->priv_in_range_or_end(p));
|
||||||
return this->priv_forward_range_insert
|
typedef typename dtl::if_c < boost::move_detail::is_rvalue_reference<BOOST_FWD_REF(U)>::value
|
||||||
( vector_iterator_get_ptr(p), 1, dtl::get_insert_value_proxy<T*, allocator_type>(::boost::forward<U>(x)));
|
, dtl::insert_move_proxy<allocator_type, T*>
|
||||||
|
, dtl::insert_copy_proxy<allocator_type, T*>
|
||||||
|
>::type proxy_t;
|
||||||
|
return this->priv_insert_forward_range
|
||||||
|
( vector_iterator_get_ptr(p), 1, proxy_t((reference)u));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_CONTAINER_FORCEINLINE dtl::insert_copy_proxy<allocator_type, T*> priv_single_insert_proxy(const T &x)
|
|
||||||
{ return dtl::insert_copy_proxy<allocator_type, T*> (x); }
|
|
||||||
|
|
||||||
BOOST_CONTAINER_FORCEINLINE dtl::insert_move_proxy<allocator_type, T*> priv_single_insert_proxy(BOOST_RV_REF(T) x)
|
|
||||||
{ return dtl::insert_move_proxy<allocator_type, T*> (x); }
|
|
||||||
|
|
||||||
template <class U>
|
template <class U>
|
||||||
BOOST_CONTAINER_FORCEINLINE void priv_push_back(BOOST_FWD_REF(U) u)
|
BOOST_CONTAINER_FORCEINLINE void priv_push_back(BOOST_FWD_REF(U) u)
|
||||||
{
|
{
|
||||||
@@ -2623,9 +2621,12 @@ private:
|
|||||||
++this->m_holder.m_size;
|
++this->m_holder.m_size;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
this->priv_forward_range_insert_no_capacity
|
typedef typename dtl::if_c < boost::move_detail::is_rvalue_reference<BOOST_FWD_REF(U)>::value
|
||||||
( this->back_ptr(), 1
|
, dtl::insert_move_proxy<allocator_type, T*>
|
||||||
, this->priv_single_insert_proxy(::boost::forward<U>(u)), alloc_version());
|
, dtl::insert_copy_proxy<allocator_type, T*>
|
||||||
|
>::type proxy_t;
|
||||||
|
this->priv_insert_forward_range_no_capacity
|
||||||
|
( this->back_ptr(), 1, proxy_t((reference)u), alloc_version());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2638,20 +2639,6 @@ private:
|
|||||||
BOOST_CONTAINER_FORCEINLINE dtl::insert_value_initialized_n_proxy<allocator_type, T*> priv_resize_proxy(value_init_t)
|
BOOST_CONTAINER_FORCEINLINE dtl::insert_value_initialized_n_proxy<allocator_type, T*> priv_resize_proxy(value_init_t)
|
||||||
{ return dtl::insert_value_initialized_n_proxy<allocator_type, T*>(); }
|
{ return dtl::insert_value_initialized_n_proxy<allocator_type, T*>(); }
|
||||||
|
|
||||||
template <class U>
|
|
||||||
void priv_resize(size_type new_size, const U& u)
|
|
||||||
{
|
|
||||||
const size_type sz = this->size();
|
|
||||||
if (new_size < sz){
|
|
||||||
//Destroy last elements
|
|
||||||
this->priv_destroy_last_n(sz - new_size);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
const size_type n = new_size - this->size();
|
|
||||||
this->priv_forward_range_insert_at_end(n, this->priv_resize_proxy(u), alloc_version());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_CONTAINER_FORCEINLINE void priv_shrink_to_fit(version_0) BOOST_NOEXCEPT_OR_NOTHROW
|
BOOST_CONTAINER_FORCEINLINE void priv_shrink_to_fit(version_0) BOOST_NOEXCEPT_OR_NOTHROW
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -2667,17 +2654,7 @@ private:
|
|||||||
this->m_holder.m_capacity = 0;
|
this->m_holder.m_capacity = 0;
|
||||||
}
|
}
|
||||||
else if(sz < cp){
|
else if(sz < cp){
|
||||||
//Allocate a new buffer.
|
this->priv_move_to_new_buffer(sz, alloc_version());
|
||||||
//Pass the hint so that allocators can take advantage of this.
|
|
||||||
pointer const p = this->m_holder.allocate(sz);
|
|
||||||
|
|
||||||
//We will reuse insert code, so create a dummy input iterator
|
|
||||||
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
|
||||||
++this->num_alloc;
|
|
||||||
#endif
|
|
||||||
this->priv_forward_range_insert_new_allocation
|
|
||||||
( boost::movelib::to_raw_pointer(p), sz
|
|
||||||
, this->priv_raw_begin(), 0, this->priv_dummy_empty_proxy());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2708,15 +2685,14 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class InsertionProxy>
|
template <class InsertionProxy>
|
||||||
iterator priv_forward_range_insert_no_capacity
|
BOOST_CONTAINER_FORCEINLINE iterator priv_insert_forward_range_no_capacity
|
||||||
(const pointer &pos, const size_type, const InsertionProxy , version_0)
|
(const pointer &, const size_type, const InsertionProxy , version_0)
|
||||||
{
|
{
|
||||||
alloc_holder_t::on_capacity_overflow();
|
return alloc_holder_t::on_capacity_overflow(), iterator();
|
||||||
return iterator(pos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class InsertionProxy>
|
template <class InsertionProxy>
|
||||||
iterator priv_forward_range_insert_no_capacity
|
BOOST_CONTAINER_FORCEINLINE iterator priv_insert_forward_range_no_capacity
|
||||||
(const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_1)
|
(const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_1)
|
||||||
{
|
{
|
||||||
//Check if we have enough memory or try to expand current memory
|
//Check if we have enough memory or try to expand current memory
|
||||||
@@ -2729,13 +2705,12 @@ private:
|
|||||||
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
||||||
++this->num_alloc;
|
++this->num_alloc;
|
||||||
#endif
|
#endif
|
||||||
this->priv_forward_range_insert_new_allocation
|
this->priv_insert_forward_range_new_allocation(new_buf, new_cap, raw_pos, n, insert_range_proxy);
|
||||||
( new_buf, new_cap, raw_pos, n, insert_range_proxy);
|
|
||||||
return iterator(this->m_holder.start() + n_pos);
|
return iterator(this->m_holder.start() + n_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class InsertionProxy>
|
template <class InsertionProxy>
|
||||||
iterator priv_forward_range_insert_no_capacity
|
iterator priv_insert_forward_range_no_capacity
|
||||||
(const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_2)
|
(const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_2)
|
||||||
{
|
{
|
||||||
//Check if we have enough memory or try to expand current memory
|
//Check if we have enough memory or try to expand current memory
|
||||||
@@ -2758,14 +2733,14 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
this->m_holder.capacity(real_cap);
|
this->m_holder.capacity(real_cap);
|
||||||
//Expand forward
|
//Expand forward
|
||||||
this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
|
this->priv_insert_forward_range_expand_forward(raw_pos, n, insert_range_proxy);
|
||||||
}
|
}
|
||||||
//Backwards (and possibly forward) expansion
|
//Backwards (and possibly forward) expansion
|
||||||
else{
|
else{
|
||||||
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
||||||
++this->num_expand_bwd;
|
++this->num_expand_bwd;
|
||||||
#endif
|
#endif
|
||||||
this->priv_forward_range_insert_expand_backwards
|
this->priv_insert_forward_range_expand_backwards
|
||||||
(boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
|
(boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2774,7 +2749,7 @@ private:
|
|||||||
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
|
||||||
++this->num_alloc;
|
++this->num_alloc;
|
||||||
#endif
|
#endif
|
||||||
this->priv_forward_range_insert_new_allocation
|
this->priv_insert_forward_range_new_allocation
|
||||||
( boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
|
( boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2782,46 +2757,52 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class InsertionProxy>
|
template <class InsertionProxy>
|
||||||
iterator priv_forward_range_insert
|
BOOST_CONTAINER_FORCEINLINE iterator priv_insert_forward_range
|
||||||
(const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy)
|
(const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(this->m_holder.capacity() >= this->m_holder.m_size);
|
BOOST_ASSERT(this->m_holder.capacity() >= this->m_holder.m_size);
|
||||||
//Check if we have enough memory or try to expand current memory
|
//Check if we have enough memory or try to expand current memory
|
||||||
const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
|
if (BOOST_LIKELY(n <= (this->m_holder.capacity() - this->m_holder.m_size))){
|
||||||
|
//Expand forward
|
||||||
bool same_buffer_start = n <= remaining;
|
this->priv_insert_forward_range_expand_forward(boost::movelib::to_raw_pointer(pos), n, insert_range_proxy);
|
||||||
if (!same_buffer_start){
|
return iterator(pos);
|
||||||
return priv_forward_range_insert_no_capacity(pos, n, insert_range_proxy, alloc_version());
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
//Expand forward
|
return this->priv_insert_forward_range_no_capacity(pos, n, insert_range_proxy, alloc_version());
|
||||||
T *const raw_pos = boost::movelib::to_raw_pointer(pos);
|
|
||||||
const size_type n_pos = raw_pos - this->priv_raw_begin();
|
|
||||||
this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
|
|
||||||
return iterator(this->m_holder.start() + n_pos);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class InsertionProxy>
|
template <class U>
|
||||||
iterator priv_forward_range_insert_at_end
|
void priv_resize(const size_type new_size, const U &u, version_0)
|
||||||
(const size_type n, const InsertionProxy insert_range_proxy, version_0)
|
|
||||||
{
|
{
|
||||||
//Check if we have enough memory or try to expand current memory
|
const size_type sz = this->m_holder.m_size;
|
||||||
const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
|
if (new_size > this->capacity()){
|
||||||
|
|
||||||
if (n > remaining){
|
|
||||||
//This will trigger an error
|
//This will trigger an error
|
||||||
alloc_holder_t::on_capacity_overflow();
|
alloc_holder_t::on_capacity_overflow();
|
||||||
}
|
}
|
||||||
this->priv_forward_range_insert_at_end_expand_forward(n, insert_range_proxy);
|
else if (new_size < sz){
|
||||||
return this->end();
|
//Destroy last elements
|
||||||
|
this->priv_destroy_last_n(sz - new_size);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
T* const old_finish = this->priv_raw_end();
|
||||||
|
this->priv_resize_proxy(u).uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, new_size - sz);
|
||||||
|
this->m_holder.set_stored_size(new_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class InsertionProxy, class AllocVersion>
|
template <class U, class AllocVersion>
|
||||||
BOOST_CONTAINER_FORCEINLINE iterator priv_forward_range_insert_at_end
|
BOOST_CONTAINER_FORCEINLINE void priv_resize
|
||||||
(const size_type n, const InsertionProxy insert_range_proxy, AllocVersion)
|
(const size_type new_size, const U &u, AllocVersion)
|
||||||
{
|
{
|
||||||
return this->priv_forward_range_insert(this->back_ptr(), n, insert_range_proxy);
|
const size_type sz = this->m_holder.m_size;
|
||||||
|
if (new_size < sz){
|
||||||
|
//Destroy last elements
|
||||||
|
this->priv_destroy_last_n(sz - new_size);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->priv_insert_forward_range(this->back_ptr(), new_size - sz, this->priv_resize_proxy(u));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Takes the range pointed by [first_pos, last_pos) and shifts it to the right
|
//Takes the range pointed by [first_pos, last_pos) and shifts it to the right
|
||||||
@@ -2918,86 +2899,89 @@ private:
|
|||||||
{ return this->priv_raw_begin() + this->m_holder.m_size; }
|
{ return this->priv_raw_begin() + this->m_holder.m_size; }
|
||||||
|
|
||||||
template <class InsertionProxy>
|
template <class InsertionProxy>
|
||||||
void priv_forward_range_insert_at_end_expand_forward(const size_type n, InsertionProxy insert_range_proxy)
|
BOOST_CONTAINER_FORCEINLINE void priv_insert_forward_range_expand_forward(T* const raw_pos, const size_type n, InsertionProxy insert_range_proxy)
|
||||||
{
|
|
||||||
T* const old_finish = this->priv_raw_end();
|
|
||||||
insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
|
|
||||||
this->m_holder.m_size += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class InsertionProxy>
|
|
||||||
void priv_forward_range_insert_expand_forward(T* const pos, const size_type n, InsertionProxy insert_range_proxy)
|
|
||||||
{
|
{
|
||||||
//n can't be 0, because there is nothing to do in that case
|
//n can't be 0, because there is nothing to do in that case
|
||||||
if(BOOST_UNLIKELY(!n)) return;
|
bool const single_value_proxy = dtl::is_single_value_proxy<InsertionProxy>::value;
|
||||||
|
//bool const single_value_proxy = false;
|
||||||
|
if(BOOST_UNLIKELY(!single_value_proxy && !n))
|
||||||
|
return;
|
||||||
|
|
||||||
//There is enough memory
|
//There is enough memory
|
||||||
T* const old_finish = this->priv_raw_end();
|
T* const old_finish = this->priv_raw_end();
|
||||||
const size_type elems_after = old_finish - pos;
|
const size_type elems_after = old_finish - raw_pos;
|
||||||
|
allocator_type & a = this->m_holder.alloc();
|
||||||
|
|
||||||
if (!elems_after){
|
if (!elems_after){
|
||||||
insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
|
insert_range_proxy.uninitialized_copy_n_and_update(a, old_finish, n);
|
||||||
this->m_holder.m_size += n;
|
this->m_holder.m_size += static_cast<stored_size_type>(n);
|
||||||
}
|
}
|
||||||
else if (elems_after >= n){
|
else if(single_value_proxy){
|
||||||
//New elements can be just copied.
|
//New elements can be just copied.
|
||||||
//Move to uninitialized memory last objects
|
//Move to uninitialized memory last objects
|
||||||
::boost::container::uninitialized_move_alloc
|
allocator_traits_type::construct(a, old_finish, ::boost::move(*(old_finish-1)));
|
||||||
(this->m_holder.alloc(), old_finish - n, old_finish, old_finish);
|
++this->m_holder.m_size;
|
||||||
this->m_holder.m_size += n;
|
|
||||||
//Copy previous to last objects to the initialized end
|
//Copy previous to last objects to the initialized end
|
||||||
boost::container::move_backward(pos, old_finish - n, old_finish);
|
boost::container::move_backward(raw_pos, old_finish - 1, old_finish);
|
||||||
//Insert new objects in the pos
|
//Insert new objects in the raw_pos
|
||||||
insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, n);
|
insert_range_proxy.copy_n_and_update(a, raw_pos, 1);
|
||||||
|
}
|
||||||
|
else if(elems_after >= n){
|
||||||
|
//New elements can be just copied.
|
||||||
|
//Move to uninitialized memory last objects
|
||||||
|
::boost::container::uninitialized_move_alloc_n(a, old_finish - n, n, old_finish);
|
||||||
|
this->m_holder.m_size += static_cast<stored_size_type>(n);
|
||||||
|
//Copy previous to last objects to the initialized end
|
||||||
|
boost::container::move_backward(raw_pos, old_finish - n, old_finish);
|
||||||
|
//Insert new objects in the raw_pos
|
||||||
|
insert_range_proxy.copy_n_and_update(a, raw_pos, n);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//The new elements don't fit in the [pos, end()) range.
|
//The new elements don't fit in the [raw_pos, end()) range.
|
||||||
|
//Copy old [raw_pos, end()) elements to the uninitialized memory (a gap is created)
|
||||||
//Copy old [pos, end()) elements to the uninitialized memory (a gap is created)
|
::boost::container::uninitialized_move_alloc(a, raw_pos, old_finish, raw_pos + n);
|
||||||
::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), pos, old_finish, pos + n);
|
typename value_traits::ArrayDestructor on_exception(raw_pos + n, a, elems_after);
|
||||||
BOOST_TRY{
|
//Copy first new elements in raw_pos (gap is still there)
|
||||||
//Copy first new elements in pos (gap is still there)
|
insert_range_proxy.copy_n_and_update(a, raw_pos, elems_after);
|
||||||
insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, elems_after);
|
//Copy to the beginning of the unallocated zone the last new elements (the gap is closed).
|
||||||
//Copy to the beginning of the unallocated zone the last new elements (the gap is closed).
|
insert_range_proxy.uninitialized_copy_n_and_update(a, old_finish, n - elems_after);
|
||||||
insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n - elems_after);
|
this->m_holder.m_size += static_cast<stored_size_type>(n);
|
||||||
this->m_holder.m_size += n;
|
on_exception.release();
|
||||||
}
|
|
||||||
BOOST_CATCH(...){
|
|
||||||
boost::container::destroy_alloc_n(this->get_stored_allocator(), pos + n, elems_after);
|
|
||||||
BOOST_RETHROW
|
|
||||||
}
|
|
||||||
BOOST_CATCH_END
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class InsertionProxy>
|
template <class InsertionProxy>
|
||||||
void priv_forward_range_insert_new_allocation
|
void priv_insert_forward_range_new_allocation
|
||||||
(T* const new_start, size_type new_cap, T* const pos, const size_type n, InsertionProxy insert_range_proxy)
|
(T* const new_start, size_type new_cap, T* const pos, const size_type n, InsertionProxy insert_range_proxy)
|
||||||
{
|
{
|
||||||
//n can be zero, if we want to reallocate!
|
//n can be zero, if we want to reallocate!
|
||||||
T *new_finish = new_start;
|
T *new_finish = new_start;
|
||||||
T *old_finish;
|
T *old_finish;
|
||||||
|
|
||||||
|
allocator_type &a = this->m_holder.alloc();
|
||||||
|
|
||||||
//Anti-exception rollbacks
|
//Anti-exception rollbacks
|
||||||
typename value_traits::ArrayDeallocator new_buffer_deallocator(new_start, this->m_holder.alloc(), new_cap);
|
typename value_traits::ArrayDeallocator new_buffer_deallocator(new_start, a, new_cap);
|
||||||
typename value_traits::ArrayDestructor new_values_destroyer(new_start, this->m_holder.alloc(), 0u);
|
typename value_traits::ArrayDestructor new_values_destroyer(new_start, a, 0u);
|
||||||
|
|
||||||
//Initialize with [begin(), pos) old buffer
|
//Initialize with [begin(), pos) old buffer
|
||||||
//the start of the new buffer
|
//the start of the new buffer
|
||||||
T * const old_buffer = this->priv_raw_begin();
|
T * const old_buffer = this->priv_raw_begin();
|
||||||
if(old_buffer){
|
if(old_buffer){
|
||||||
new_finish = ::boost::container::uninitialized_move_alloc
|
new_finish = ::boost::container::uninitialized_move_alloc
|
||||||
(this->m_holder.alloc(), this->priv_raw_begin(), pos, old_finish = new_finish);
|
(a, this->priv_raw_begin(), pos, old_finish = new_finish);
|
||||||
new_values_destroyer.increment_size(new_finish - old_finish);
|
new_values_destroyer.increment_size(new_finish - old_finish);
|
||||||
}
|
}
|
||||||
//Initialize new objects, starting from previous point
|
//Initialize new objects, starting from previous point
|
||||||
old_finish = new_finish;
|
old_finish = new_finish;
|
||||||
insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
|
insert_range_proxy.uninitialized_copy_n_and_update(a, old_finish, n);
|
||||||
new_finish += n;
|
new_finish += n;
|
||||||
new_values_destroyer.increment_size(new_finish - old_finish);
|
new_values_destroyer.increment_size(new_finish - old_finish);
|
||||||
//Initialize from the rest of the old buffer,
|
//Initialize from the rest of the old buffer,
|
||||||
//starting from previous point
|
//starting from previous point
|
||||||
if(old_buffer){
|
if(old_buffer){
|
||||||
new_finish = ::boost::container::uninitialized_move_alloc
|
new_finish = ::boost::container::uninitialized_move_alloc
|
||||||
(this->m_holder.alloc(), pos, old_buffer + this->m_holder.m_size, new_finish);
|
(a, pos, old_buffer + this->m_holder.m_size, new_finish);
|
||||||
//Destroy and deallocate old elements
|
//Destroy and deallocate old elements
|
||||||
//If there is allocated memory, destroy and deallocate
|
//If there is allocated memory, destroy and deallocate
|
||||||
if(!value_traits::trivial_dctr_after_move)
|
if(!value_traits::trivial_dctr_after_move)
|
||||||
@@ -3005,7 +2989,7 @@ private:
|
|||||||
this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity());
|
this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity());
|
||||||
}
|
}
|
||||||
this->m_holder.start(new_start);
|
this->m_holder.start(new_start);
|
||||||
this->m_holder.m_size = size_type(new_finish - new_start);
|
m_holder.set_stored_size(new_finish - new_start);
|
||||||
this->m_holder.capacity(new_cap);
|
this->m_holder.capacity(new_cap);
|
||||||
//All construction successful, disable rollbacks
|
//All construction successful, disable rollbacks
|
||||||
new_values_destroyer.release();
|
new_values_destroyer.release();
|
||||||
@@ -3013,7 +2997,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class InsertionProxy>
|
template <class InsertionProxy>
|
||||||
void priv_forward_range_insert_expand_backwards
|
void priv_insert_forward_range_expand_backwards
|
||||||
(T* const new_start, const size_type new_capacity,
|
(T* const new_start, const size_type new_capacity,
|
||||||
T* const pos, const size_type n, InsertionProxy insert_range_proxy)
|
T* const pos, const size_type n, InsertionProxy insert_range_proxy)
|
||||||
{
|
{
|
||||||
@@ -3022,27 +3006,30 @@ private:
|
|||||||
T* const old_start = this->priv_raw_begin();
|
T* const old_start = this->priv_raw_begin();
|
||||||
const size_type old_size = this->m_holder.m_size;
|
const size_type old_size = this->m_holder.m_size;
|
||||||
T* const old_finish = old_start + old_size;
|
T* const old_finish = old_start + old_size;
|
||||||
|
allocator_type &a = this->m_holder.alloc();
|
||||||
//We can have 8 possibilities:
|
|
||||||
const size_type elemsbefore = static_cast<size_type>(pos - old_start);
|
|
||||||
const size_type s_before = static_cast<size_type>(old_start - new_start);
|
|
||||||
const size_type before_plus_new = elemsbefore + n;
|
|
||||||
|
|
||||||
//Update the vector buffer information to a safe state
|
//Update the vector buffer information to a safe state
|
||||||
this->m_holder.start(new_start);
|
this->m_holder.start(new_start);
|
||||||
this->m_holder.capacity(new_capacity);
|
this->m_holder.capacity(new_capacity);
|
||||||
this->m_holder.m_size = 0;
|
this->m_holder.m_size = 0;
|
||||||
|
|
||||||
|
//We can have 8 possibilities:
|
||||||
|
const size_type elemsbefore = static_cast<size_type>(pos - old_start);
|
||||||
|
const size_type s_before = static_cast<size_type>(old_start - new_start);
|
||||||
|
const size_type before_plus_new = elemsbefore + n;
|
||||||
|
|
||||||
|
typedef typename value_traits::ArrayDestructor array_destructor_t;
|
||||||
|
|
||||||
//If anything goes wrong, this object will destroy
|
//If anything goes wrong, this object will destroy
|
||||||
//all the old objects to fulfill previous vector state
|
//all the old objects to fulfill previous vector state
|
||||||
typename value_traits::ArrayDestructor old_values_destroyer(old_start, this->m_holder.alloc(), old_size);
|
array_destructor_t old_values_destroyer(old_start, a, old_size);
|
||||||
//Check if s_before is big enough to hold the beginning of old data + new data
|
//Check if s_before is big enough to hold the beginning of old data + new data
|
||||||
if(s_before >= before_plus_new){
|
if(s_before >= before_plus_new){
|
||||||
//Copy first old values before pos, after that the new objects
|
//Copy first old values before pos, after that the new objects
|
||||||
T *const new_elem_pos =
|
T *const new_elem_pos =
|
||||||
::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), old_start, pos, new_start);
|
::boost::container::uninitialized_move_alloc(a, old_start, pos, new_start);
|
||||||
this->m_holder.set_stored_size(elemsbefore);
|
this->m_holder.set_stored_size(elemsbefore);
|
||||||
insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), new_elem_pos, n);
|
insert_range_proxy.uninitialized_copy_n_and_update(a, new_elem_pos, n);
|
||||||
this->m_holder.set_stored_size(before_plus_new);
|
this->m_holder.set_stored_size(before_plus_new);
|
||||||
const size_type new_size = old_size + n;
|
const size_type new_size = old_size + n;
|
||||||
//Check if s_before is so big that even copying the old data + new data
|
//Check if s_before is so big that even copying the old data + new data
|
||||||
@@ -3060,15 +3047,14 @@ private:
|
|||||||
//
|
//
|
||||||
//Now initialize the rest of memory with the last old values
|
//Now initialize the rest of memory with the last old values
|
||||||
if(before_plus_new != new_size){ //Special case to avoid operations in back insertion
|
if(before_plus_new != new_size){ //Special case to avoid operations in back insertion
|
||||||
::boost::container::uninitialized_move_alloc
|
::boost::container::uninitialized_move_alloc(a, pos, old_finish, new_start + before_plus_new);
|
||||||
(this->m_holder.alloc(), pos, old_finish, new_start + before_plus_new);
|
|
||||||
//All new elements correctly constructed, avoid new element destruction
|
//All new elements correctly constructed, avoid new element destruction
|
||||||
this->m_holder.set_stored_size(new_size);
|
this->m_holder.set_stored_size(new_size);
|
||||||
}
|
}
|
||||||
//Old values destroyed automatically with "old_values_destroyer"
|
//Old values destroyed automatically with "old_values_destroyer"
|
||||||
//when "old_values_destroyer" goes out of scope unless the have trivial
|
//when "old_values_destroyer" goes out of scope unless the have trivial
|
||||||
//destructor after move.
|
//destructor after move.
|
||||||
if(value_traits::trivial_dctr_after_move)
|
BOOST_IF_CONSTEXPR(value_traits::trivial_dctr_after_move)
|
||||||
old_values_destroyer.release();
|
old_values_destroyer.release();
|
||||||
}
|
}
|
||||||
//s_before is so big that divides old_end
|
//s_before is so big that divides old_end
|
||||||
@@ -3086,11 +3072,10 @@ private:
|
|||||||
//Now initialize the rest of memory with the last old values
|
//Now initialize the rest of memory with the last old values
|
||||||
//All new elements correctly constructed, avoid new element destruction
|
//All new elements correctly constructed, avoid new element destruction
|
||||||
const size_type raw_gap = s_before - before_plus_new;
|
const size_type raw_gap = s_before - before_plus_new;
|
||||||
if(!value_traits::trivial_dctr){
|
BOOST_IF_CONSTEXPR(!value_traits::trivial_dctr){
|
||||||
//Now initialize the rest of s_before memory with the
|
//Now initialize the rest of s_before memory with the
|
||||||
//first of elements after new values
|
//first of elements after new values
|
||||||
::boost::container::uninitialized_move_alloc_n
|
::boost::container::uninitialized_move_alloc_n(a, pos, raw_gap, new_start + before_plus_new);
|
||||||
(this->m_holder.alloc(), pos, raw_gap, new_start + before_plus_new);
|
|
||||||
//Now we have a contiguous buffer so program trailing element destruction
|
//Now we have a contiguous buffer so program trailing element destruction
|
||||||
//and update size to the final size.
|
//and update size to the final size.
|
||||||
old_values_destroyer.shrink_forward(new_size-s_before);
|
old_values_destroyer.shrink_forward(new_size-s_before);
|
||||||
@@ -3101,13 +3086,13 @@ private:
|
|||||||
::boost::container::move(remaining_pos, old_finish, old_start);
|
::boost::container::move(remaining_pos, old_finish, old_start);
|
||||||
}
|
}
|
||||||
//Once moved, avoid calling the destructors if trivial after move
|
//Once moved, avoid calling the destructors if trivial after move
|
||||||
if(value_traits::trivial_dctr_after_move){
|
BOOST_IF_CONSTEXPR(value_traits::trivial_dctr_after_move){
|
||||||
old_values_destroyer.release();
|
old_values_destroyer.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{ //If trivial destructor, we can uninitialized copy + copy in a single uninitialized copy
|
else{ //If trivial destructor, we can uninitialized copy + copy in a single uninitialized copy
|
||||||
::boost::container::uninitialized_move_alloc_n
|
::boost::container::uninitialized_move_alloc_n
|
||||||
(this->m_holder.alloc(), pos, static_cast<size_type>(old_finish - pos), new_start + before_plus_new);
|
(a, pos, static_cast<size_type>(old_finish - pos), new_start + before_plus_new);
|
||||||
this->m_holder.set_stored_size(new_size);
|
this->m_holder.set_stored_size(new_size);
|
||||||
old_values_destroyer.release();
|
old_values_destroyer.release();
|
||||||
}
|
}
|
||||||
@@ -3162,8 +3147,7 @@ private:
|
|||||||
//|___________|_____|_________|_____________________|
|
//|___________|_____|_________|_____________________|
|
||||||
//
|
//
|
||||||
//Copy the first part of old_begin to raw_mem
|
//Copy the first part of old_begin to raw_mem
|
||||||
::boost::container::uninitialized_move_alloc_n
|
::boost::container::uninitialized_move_alloc_n(a, old_start, s_before, new_start);
|
||||||
(this->m_holder.alloc(), old_start, s_before, new_start);
|
|
||||||
//The buffer is all constructed until old_end,
|
//The buffer is all constructed until old_end,
|
||||||
//so program trailing destruction and assign final size
|
//so program trailing destruction and assign final size
|
||||||
//if !do_after, s_before+n otherwise.
|
//if !do_after, s_before+n otherwise.
|
||||||
@@ -3175,8 +3159,9 @@ private:
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
new_1st_range = n;
|
new_1st_range = n;
|
||||||
if(value_traits::trivial_dctr_after_move)
|
BOOST_IF_CONSTEXPR(value_traits::trivial_dctr_after_move){
|
||||||
old_values_destroyer.release();
|
old_values_destroyer.release();
|
||||||
|
}
|
||||||
else{
|
else{
|
||||||
old_values_destroyer.shrink_forward(old_size - (s_before - n));
|
old_values_destroyer.shrink_forward(old_size - (s_before - n));
|
||||||
}
|
}
|
||||||
@@ -3185,7 +3170,7 @@ private:
|
|||||||
//Now copy the second part of old_begin overwriting itself
|
//Now copy the second part of old_begin overwriting itself
|
||||||
T *const next = ::boost::container::move(old_start + s_before, pos, old_start);
|
T *const next = ::boost::container::move(old_start + s_before, pos, old_start);
|
||||||
//Now copy the new_beg elements
|
//Now copy the new_beg elements
|
||||||
insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), next, new_1st_range);
|
insert_range_proxy.copy_n_and_update(a, next, new_1st_range);
|
||||||
|
|
||||||
//If there is no after work and the last old part needs to be moved to front, do it
|
//If there is no after work and the last old part needs to be moved to front, do it
|
||||||
if(!do_after && (n != s_before)){
|
if(!do_after && (n != s_before)){
|
||||||
@@ -3221,10 +3206,10 @@ private:
|
|||||||
//
|
//
|
||||||
//First copy whole old_begin and part of new to raw_mem
|
//First copy whole old_begin and part of new to raw_mem
|
||||||
T * const new_pos = ::boost::container::uninitialized_move_alloc
|
T * const new_pos = ::boost::container::uninitialized_move_alloc
|
||||||
(this->m_holder.alloc(), old_start, pos, new_start);
|
(a, old_start, pos, new_start);
|
||||||
this->m_holder.set_stored_size(elemsbefore);
|
this->m_holder.set_stored_size(elemsbefore);
|
||||||
const size_type mid_n = s_before - elemsbefore;
|
const size_type mid_n = s_before - elemsbefore;
|
||||||
insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), new_pos, mid_n);
|
insert_range_proxy.uninitialized_copy_n_and_update(a, new_pos, mid_n);
|
||||||
//The buffer is all constructed until old_end,
|
//The buffer is all constructed until old_end,
|
||||||
//release destroyer
|
//release destroyer
|
||||||
this->m_holder.set_stored_size(old_size + s_before);
|
this->m_holder.set_stored_size(old_size + s_before);
|
||||||
@@ -3232,12 +3217,12 @@ private:
|
|||||||
|
|
||||||
if(do_after){
|
if(do_after){
|
||||||
//Copy new_beg part
|
//Copy new_beg part
|
||||||
insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, elemsbefore);
|
insert_range_proxy.copy_n_and_update(a, old_start, elemsbefore);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
//Copy all new elements
|
//Copy all new elements
|
||||||
const size_type rest_new = n - mid_n;
|
const size_type rest_new = n - mid_n;
|
||||||
insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, rest_new);
|
insert_range_proxy.copy_n_and_update(a, old_start, rest_new);
|
||||||
T* const move_start = old_start + rest_new;
|
T* const move_start = old_start + rest_new;
|
||||||
//Displace old_end, but make sure data has to be moved
|
//Displace old_end, but make sure data has to be moved
|
||||||
T* const move_end = move_start != pos ? ::boost::container::move(pos, old_finish, move_start)
|
T* const move_end = move_start != pos ? ::boost::container::move(pos, old_finish, move_start)
|
||||||
@@ -3245,8 +3230,9 @@ private:
|
|||||||
//Destroy remaining moved elements from old_end except if they
|
//Destroy remaining moved elements from old_end except if they
|
||||||
//have trivial destructor after being moved
|
//have trivial destructor after being moved
|
||||||
size_type n_destroy = s_before - n;
|
size_type n_destroy = s_before - n;
|
||||||
if(!value_traits::trivial_dctr_after_move)
|
BOOST_IF_CONSTEXPR(!value_traits::trivial_dctr_after_move){
|
||||||
boost::container::destroy_alloc_n(this->get_stored_allocator(), move_end, n_destroy);
|
boost::container::destroy_alloc_n(a, move_end, n_destroy);
|
||||||
|
}
|
||||||
this->m_holder.set_stored_size(this->size() - n_destroy);
|
this->m_holder.set_stored_size(this->size() - n_destroy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3289,14 +3275,13 @@ private:
|
|||||||
//
|
//
|
||||||
//First copy the part of old_end raw_mem
|
//First copy the part of old_end raw_mem
|
||||||
T* finish_n = old_finish - n_after;
|
T* finish_n = old_finish - n_after;
|
||||||
::boost::container::uninitialized_move_alloc
|
::boost::container::uninitialized_move_alloc(a, finish_n, old_finish, old_finish);
|
||||||
(this->m_holder.alloc(), finish_n, old_finish, old_finish);
|
|
||||||
this->m_holder.set_stored_size(this->size() + n_after);
|
this->m_holder.set_stored_size(this->size() + n_after);
|
||||||
//Displace the rest of old_end to the new position
|
//Displace the rest of old_end to the new position
|
||||||
boost::container::move_backward(pos, finish_n, old_finish);
|
boost::container::move_backward(pos, finish_n, old_finish);
|
||||||
//Now overwrite with new_end
|
//Now overwrite with new_end
|
||||||
//The new_end part is [first + (n - n_after), last)
|
//The new_end part is [first + (n - n_after), last)
|
||||||
insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, n_after);
|
insert_range_proxy.copy_n_and_update(a, pos, n_after);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//The raw_mem from end will divide new_end part
|
//The raw_mem from end will divide new_end part
|
||||||
@@ -3310,22 +3295,19 @@ private:
|
|||||||
// _____________________________________________________________
|
// _____________________________________________________________
|
||||||
//| old_begin + new_beg | new_end |old_end | raw_mem |
|
//| old_begin + new_beg | new_end |old_end | raw_mem |
|
||||||
//|__________________________|_______________|________|_________|
|
//|__________________________|_______________|________|_________|
|
||||||
//
|
|
||||||
|
|
||||||
const size_type mid_last_dist = n_after - elemsafter;
|
|
||||||
//First initialize data in raw memory
|
//First initialize data in raw memory
|
||||||
|
const size_type mid_last_dist = n_after - elemsafter;
|
||||||
|
|
||||||
//Copy to the old_end part to the uninitialized zone leaving a gap.
|
//Copy to the old_end part to the uninitialized zone leaving a gap.
|
||||||
::boost::container::uninitialized_move_alloc
|
::boost::container::uninitialized_move_alloc(a, pos, old_finish, old_finish + mid_last_dist);
|
||||||
(this->m_holder.alloc(), pos, old_finish, old_finish + mid_last_dist);
|
|
||||||
|
|
||||||
typename value_traits::ArrayDestructor old_end_destroyer
|
array_destructor_t old_end_destroyer(old_finish + mid_last_dist, a, old_finish - pos);
|
||||||
(old_finish + mid_last_dist, this->m_holder.alloc(), old_finish - pos);
|
|
||||||
|
|
||||||
//Copy the first part to the already constructed old_end zone
|
//Copy the first part to the already constructed old_end zone
|
||||||
insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, elemsafter);
|
insert_range_proxy.copy_n_and_update(a, pos, elemsafter);
|
||||||
//Copy the rest to the uninitialized zone filling the gap
|
//Copy the rest to the uninitialized zone filling the gap
|
||||||
insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, mid_last_dist);
|
insert_range_proxy.uninitialized_copy_n_and_update(a, old_finish, mid_last_dist);
|
||||||
this->m_holder.set_stored_size(this->size() + n_after);
|
this->m_holder.set_stored_size(this->size() + n_after);
|
||||||
old_end_destroyer.release();
|
old_end_destroyer.release();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user