forked from boostorg/container
Updated scoped allocator support
[SVN r77911]
This commit is contained in:
@@ -1463,9 +1463,10 @@ class vector : private container_detail::vector_alloc_holder<A>
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template<class BiDirIt>
|
||||
void insert_at_ordered_positions(const size_type *positions, size_type element_count, BiDirIt end)
|
||||
public:
|
||||
//Absolutely experimental. This function might change, disappear or simply crash!
|
||||
template<class BiDirPosIt, class BiDirValueIt>
|
||||
void insert_ordered_at(size_type element_count, BiDirPosIt last_position_it, BiDirValueIt last_value_it)
|
||||
{
|
||||
const size_type old_size_pos = this->size();
|
||||
this->reserve(old_size_pos + element_count);
|
||||
@@ -1481,16 +1482,16 @@ class vector : private container_detail::vector_alloc_holder<A>
|
||||
//Loop for each insertion backwards, first moving the elements after the insertion point,
|
||||
//then inserting the element.
|
||||
while(insertions_left){
|
||||
const size_type pos = positions[insertions_left - 1];
|
||||
const size_type pos = static_cast<size_type>(*(--last_position_it));
|
||||
BOOST_ASSERT(pos <= old_size_pos);
|
||||
//Shift the range after the insertion point, function will take care if the shift
|
||||
//crosses the size() boundary, using copy/move or uninitialized copy/move if necessary.
|
||||
size_type new_hole_size = shift_range(pos, next_pos, this->size(), insertions_left);
|
||||
size_type new_hole_size = insert_ordered_at_shift_range(pos, next_pos, this->size(), insertions_left);
|
||||
if(new_hole_size > 0){
|
||||
//The hole was reduced by shift_range so expand exception rollback range backwards
|
||||
//The hole was reduced by insert_ordered_at_shift_range so expand exception rollback range backwards
|
||||
past_hole_values_destroyer.increment_size_backwards(next_pos - pos);
|
||||
//Insert the new value in the hole
|
||||
allocator_traits_type::construct(this->alloc(), begin_ptr + pos + insertions_left - 1, *(--end));
|
||||
allocator_traits_type::construct(this->alloc(), begin_ptr + pos + insertions_left - 1, *(--last_value_it));
|
||||
--new_hole_size;
|
||||
if(new_hole_size == 0){
|
||||
//Hole was just filled, disable exception rollback and change vector size
|
||||
@@ -1504,12 +1505,12 @@ class vector : private container_detail::vector_alloc_holder<A>
|
||||
}
|
||||
else{
|
||||
if(hole_size){
|
||||
//Hole was just filled by shift_range, disable exception rollback and change vector size
|
||||
//Hole was just filled by insert_ordered_at_shift_range, disable exception rollback and change vector size
|
||||
past_hole_values_destroyer.release();
|
||||
this->members_.m_size += element_count;
|
||||
}
|
||||
//Insert the new value in the already constructed range
|
||||
begin_ptr[pos + insertions_left - 1] = *(--end);
|
||||
begin_ptr[pos + insertions_left - 1] = *(--last_value_it);
|
||||
}
|
||||
--insertions_left;
|
||||
hole_size = new_hole_size;
|
||||
@@ -1517,7 +1518,58 @@ class vector : private container_detail::vector_alloc_holder<A>
|
||||
}
|
||||
}
|
||||
|
||||
size_type shift_range(size_type first_pos, size_type last_pos, size_type limit_pos, size_type shift_count)
|
||||
//Takes the range pointed by [first_pos, last_pos) and shifts it to the right
|
||||
//by 'shift_count'. 'limit_pos' marks the end of constructed elements.
|
||||
//
|
||||
//Precondition: first_pos <= last_pos <= limit_pos
|
||||
//
|
||||
//The shift operation might cross limit_pos so elements to moved beyond limit_pos
|
||||
//are uninitialized_moved with an allocator. Other elements are moved.
|
||||
//
|
||||
//The shift operation might left uninitialized elements after limit_pos
|
||||
//and the number of uninitialized elements is returned by the function.
|
||||
//
|
||||
//Old situation:
|
||||
// first_pos last_pos old_limit
|
||||
// | | |
|
||||
// ____________V_______V__________________V_____________
|
||||
//| prefix | range | suffix |raw_mem ~
|
||||
//|____________|_______|__________________|_____________~
|
||||
//
|
||||
//New situation in Case A (hole_size == 0):
|
||||
// range is moved through move assignments
|
||||
//
|
||||
// first_pos last_pos old_limit
|
||||
// | | |
|
||||
// ____________V_______V__________________V_____________
|
||||
//| prefix' | | | range |suffix'|raw_mem ~
|
||||
//|________________+______|___^___|_______|_____________~
|
||||
// | |
|
||||
// |_>_>_>_>_>^
|
||||
//
|
||||
//
|
||||
//New situation in Case B (hole_size >= 0):
|
||||
// range is moved through uninitialized moves
|
||||
//
|
||||
// first_pos last_pos old_limit
|
||||
// | | |
|
||||
// ____________V_______V__________________V________________
|
||||
//| prefix' | | | [hole] | range |
|
||||
//|_______________________________________|________|___^___|
|
||||
// | |
|
||||
// |_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_^
|
||||
//
|
||||
//New situation in Case C (hole_size == 0):
|
||||
// range is moved through move assignments and uninitialized moves
|
||||
//
|
||||
// first_pos last_pos old_limit
|
||||
// | | |
|
||||
// ____________V_______V__________________V___
|
||||
//| prefix' | | | range |
|
||||
//|___________________________________|___^___|
|
||||
// | |
|
||||
// |_>_>_>_>_>_>_>_>_>_>_>^
|
||||
size_type insert_ordered_at_shift_range(size_type first_pos, size_type last_pos, size_type limit_pos, size_type shift_count)
|
||||
{
|
||||
BOOST_ASSERT(first_pos <= last_pos);
|
||||
BOOST_ASSERT(last_pos <= limit_pos);
|
||||
@@ -1525,20 +1577,27 @@ class vector : private container_detail::vector_alloc_holder<A>
|
||||
T* const begin_ptr = container_detail::to_raw_pointer(this->members_.m_start);
|
||||
|
||||
size_type hole_size = 0;
|
||||
if((last_pos + shift_count) < limit_pos){
|
||||
//All inside
|
||||
//Case A:
|
||||
if((last_pos + shift_count) <= limit_pos){
|
||||
//All move assigned
|
||||
boost::move_backward(begin_ptr + first_pos, begin_ptr + last_pos, begin_ptr + last_pos + shift_count);
|
||||
}
|
||||
//Case B:
|
||||
else if((first_pos + shift_count) >= limit_pos){
|
||||
//All outside
|
||||
//All uninitialized_moved
|
||||
::boost::container::uninitialized_move_alloc
|
||||
(this->alloc(), begin_ptr + first_pos, begin_ptr + last_pos, begin_ptr + first_pos + shift_count);
|
||||
hole_size = last_pos + shift_count - limit_pos;
|
||||
}
|
||||
//Case C:
|
||||
else{
|
||||
//Some uninitialized_moved
|
||||
T* const limit_ptr = begin_ptr + limit_pos;
|
||||
T* const boundary_ptr = limit_ptr - shift_count;
|
||||
::boost::container::uninitialized_move_alloc
|
||||
(this->alloc(), begin_ptr + limit_pos - shift_count, begin_ptr + last_pos, begin_ptr + limit_pos);
|
||||
boost::move_backward(begin_ptr + first_pos, begin_ptr + limit_pos - shift_count, begin_ptr + limit_pos + shift_count);
|
||||
(this->alloc(), boundary_ptr, begin_ptr + last_pos, limit_ptr);
|
||||
//The rest is move assigned
|
||||
boost::move_backward(begin_ptr + first_pos, boundary_ptr, limit_ptr + shift_count);
|
||||
}
|
||||
return hole_size;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user