mirror of
https://github.com/boostorg/container.git
synced 2025-08-02 05:54:28 +02:00
Make a different version for single value proxies in priv_insert_forward_range_expand_forward and force-inline only that version
This commit is contained in:
@@ -2685,7 +2685,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class InsertionProxy>
|
template <class InsertionProxy>
|
||||||
iterator priv_insert_forward_range_no_capacity
|
BOOST_CONTAINER_NOINLINE iterator priv_insert_forward_range_no_capacity
|
||||||
(T *const raw_pos, const size_type n, const InsertionProxy insert_range_proxy, version_1)
|
(T *const raw_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
|
||||||
@@ -2702,7 +2702,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class InsertionProxy>
|
template <class InsertionProxy>
|
||||||
iterator priv_insert_forward_range_no_capacity
|
BOOST_CONTAINER_NOINLINE iterator priv_insert_forward_range_no_capacity
|
||||||
(T *const raw_pos, const size_type n, const InsertionProxy insert_range_proxy, version_2)
|
(T *const raw_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
|
||||||
@@ -2724,7 +2724,8 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
this->m_holder.capacity(real_cap);
|
this->m_holder.capacity(real_cap);
|
||||||
//Expand forward
|
//Expand forward
|
||||||
this->priv_insert_forward_range_expand_forward(raw_pos, n, insert_range_proxy);
|
this->priv_insert_forward_range_expand_forward
|
||||||
|
(raw_pos, n, insert_range_proxy, dtl::bool_<dtl::is_single_value_proxy<InsertionProxy>::value>());
|
||||||
}
|
}
|
||||||
//Backwards (and possibly forward) expansion
|
//Backwards (and possibly forward) expansion
|
||||||
else{
|
else{
|
||||||
@@ -2748,7 +2749,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class InsertionProxy>
|
template <class InsertionProxy>
|
||||||
iterator priv_insert_forward_range
|
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);
|
||||||
@@ -2756,7 +2757,8 @@ private:
|
|||||||
//Check if we have enough memory or try to expand current memory
|
//Check if we have enough memory or try to expand current memory
|
||||||
if (BOOST_LIKELY(n <= (this->m_holder.capacity() - this->m_holder.m_size))){
|
if (BOOST_LIKELY(n <= (this->m_holder.capacity() - this->m_holder.m_size))){
|
||||||
//Expand forward
|
//Expand forward
|
||||||
this->priv_insert_forward_range_expand_forward(p, n, insert_range_proxy);
|
this->priv_insert_forward_range_expand_forward
|
||||||
|
(p, n, insert_range_proxy, dtl::bool_<dtl::is_single_value_proxy<InsertionProxy>::value>());
|
||||||
return iterator(pos);
|
return iterator(pos);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@@ -2889,55 +2891,71 @@ private:
|
|||||||
BOOST_CONTAINER_FORCEINLINE T* priv_raw_end() const
|
BOOST_CONTAINER_FORCEINLINE T* priv_raw_end() const
|
||||||
{ 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> //inline single-element version as it is significantly smaller
|
||||||
void priv_insert_forward_range_expand_forward(T* const raw_pos, 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, InsertionProxy insert_range_proxy, dtl::true_type)
|
||||||
{
|
{
|
||||||
//n can't be 0, because there is nothing to do in that case
|
BOOST_ASSERT(this->room_enough());
|
||||||
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 - raw_pos;
|
|
||||||
allocator_type & a = this->m_holder.alloc();
|
|
||||||
|
|
||||||
if (!elems_after){
|
if (old_finish == raw_pos){
|
||||||
insert_range_proxy.uninitialized_copy_n_and_update(a, old_finish, n);
|
insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, 1);
|
||||||
this->m_holder.m_size += static_cast<stored_size_type>(n);
|
++this->m_holder.m_size;
|
||||||
}
|
}
|
||||||
else if(single_value_proxy){
|
else{
|
||||||
//New elements can be just copied.
|
//New elements can be just copied.
|
||||||
//Move to uninitialized memory last objects
|
//Move to uninitialized memory last objects
|
||||||
allocator_traits_type::construct(a, old_finish, ::boost::move(*(old_finish-1)));
|
T * const before_old_finish = old_finish-1;
|
||||||
|
allocator_type & a = this->m_holder.alloc();
|
||||||
|
allocator_traits_type::construct(a, old_finish, ::boost::move(*before_old_finish));
|
||||||
++this->m_holder.m_size;
|
++this->m_holder.m_size;
|
||||||
//Copy previous to last objects to the initialized end
|
//Copy previous to last objects to the initialized end
|
||||||
boost::container::move_backward(raw_pos, old_finish - 1, old_finish);
|
boost::container::move_backward(raw_pos, before_old_finish, old_finish);
|
||||||
//Insert new objects in the raw_pos
|
//Insert new objects in the raw_pos
|
||||||
insert_range_proxy.copy_n_and_update(a, raw_pos, 1);
|
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
|
template <class InsertionProxy>
|
||||||
::boost::container::uninitialized_move_alloc_n(a, old_finish - n, n, old_finish);
|
void priv_insert_forward_range_expand_forward(T* const raw_pos, const size_type n, InsertionProxy insert_range_proxy, dtl::false_type)
|
||||||
this->m_holder.m_size += static_cast<stored_size_type>(n);
|
{
|
||||||
//Copy previous to last objects to the initialized end
|
//In case n is 0 there is nothing to do
|
||||||
boost::container::move_backward(raw_pos, old_finish - n, old_finish);
|
if(BOOST_UNLIKELY(!n))
|
||||||
//Insert new objects in the raw_pos
|
return;
|
||||||
insert_range_proxy.copy_n_and_update(a, raw_pos, n);
|
|
||||||
|
//There is enough memory
|
||||||
|
T* const raw_old_finish = this->priv_raw_end();
|
||||||
|
|
||||||
|
if (raw_old_finish == raw_pos){
|
||||||
|
insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), raw_old_finish, n);
|
||||||
|
this->m_holder.inc_stored_size(n);
|
||||||
}
|
}
|
||||||
else {
|
else{
|
||||||
//The new elements don't fit in the [raw_pos, end()) range.
|
const size_type elems_after = raw_old_finish - raw_pos;
|
||||||
//Copy old [raw_pos, end()) elements to the uninitialized memory (a gap is created)
|
allocator_type & a = this->m_holder.alloc();
|
||||||
::boost::container::uninitialized_move_alloc(a, raw_pos, old_finish, raw_pos + n);
|
if(elems_after >= n){
|
||||||
typename value_traits::ArrayDestructor on_exception(raw_pos + n, a, elems_after);
|
//New elements can be just copied.
|
||||||
//Copy first new elements in raw_pos (gap is still there)
|
//Move to uninitialized memory last objects
|
||||||
insert_range_proxy.copy_n_and_update(a, raw_pos, elems_after);
|
::boost::container::uninitialized_move_alloc_n(a, raw_old_finish - n, n, raw_old_finish);
|
||||||
//Copy to the beginning of the unallocated zone the last new elements (the gap is closed).
|
this->m_holder.inc_stored_size(n);
|
||||||
insert_range_proxy.uninitialized_copy_n_and_update(a, old_finish, n - elems_after);
|
//Copy previous to last objects to the initialized end
|
||||||
this->m_holder.m_size += static_cast<stored_size_type>(n);
|
boost::container::move_backward(raw_pos, raw_old_finish - n, raw_old_finish);
|
||||||
on_exception.release();
|
//Insert new objects in the raw_pos
|
||||||
|
insert_range_proxy.copy_n_and_update(a, raw_pos, n);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//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)
|
||||||
|
::boost::container::uninitialized_move_alloc(a, raw_pos, raw_old_finish, raw_pos + n);
|
||||||
|
typename value_traits::ArrayDestructor on_exception(raw_pos + n, a, elems_after);
|
||||||
|
//Copy first new elements in raw_pos (gap is still there)
|
||||||
|
insert_range_proxy.copy_n_and_update(a, raw_pos, elems_after);
|
||||||
|
//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, raw_old_finish, n - elems_after);
|
||||||
|
this->m_holder.inc_stored_size(n);
|
||||||
|
on_exception.release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user