Remove buffer_move_or_copy usage and reformat devector.

This commit is contained in:
Ion Gaztañaga
2026-01-02 18:30:02 +01:00
parent 84d9a29107
commit 0a0ea3e694

View File

@@ -279,8 +279,9 @@ class devector
explicit devector(size_type n, const allocator_type& allocator = allocator_type()) explicit devector(size_type n, const allocator_type& allocator = allocator_type())
: m_(reserve_uninitialized_t(), allocator, n) : m_(reserve_uninitialized_t(), allocator, n)
{ {
allocation_guard buffer_guard(m_.buffer, m_.capacity, get_allocator_ref()); allocator_type &al = this->get_allocator_ref();
boost::container::uninitialized_value_init_alloc_n(get_allocator_ref(), n, this->priv_raw_begin()); allocation_guard buffer_guard(m_.buffer, m_.capacity, al);
boost::container::uninitialized_value_init_alloc_n(al, n, this->priv_raw_begin());
buffer_guard.release(); buffer_guard.release();
BOOST_ASSERT(invariants_ok()); BOOST_ASSERT(invariants_ok());
} }
@@ -299,8 +300,9 @@ class devector
explicit devector(size_type n, default_init_t, const allocator_type& allocator = allocator_type()) explicit devector(size_type n, default_init_t, const allocator_type& allocator = allocator_type())
: m_(reserve_uninitialized_t(), allocator, n) : m_(reserve_uninitialized_t(), allocator, n)
{ {
allocation_guard buffer_guard(m_.buffer, m_.capacity, get_allocator_ref()); allocator_type &al = this->get_allocator_ref();
boost::container::uninitialized_default_init_alloc_n(get_allocator_ref(), n, this->priv_raw_begin()); allocation_guard buffer_guard(m_.buffer, m_.capacity, al);
boost::container::uninitialized_default_init_alloc_n(al, n, this->priv_raw_begin());
buffer_guard.release(); buffer_guard.release();
BOOST_ASSERT(invariants_ok()); BOOST_ASSERT(invariants_ok());
} }
@@ -544,10 +546,10 @@ class devector
size_type n = x.size(); size_type n = x.size();
if (m_.capacity >= n) { if (m_.capacity >= n) {
this->overwrite_buffer(x.begin(), x.end()); this->overwrite_buffer(x.begin(), x.end());
} }
else { else {
this->allocate_and_copy_range(x.begin(), x.end()); this->allocate_and_copy_range(x.begin(), x.end());
} }
BOOST_ASSERT(invariants_ok()); BOOST_ASSERT(invariants_ok());
@@ -1758,11 +1760,12 @@ class devector
else{ else{
iterator nonconst_pos = unconst_iterator(position); iterator nonconst_pos = unconst_iterator(position);
prefer_move_back = should_move_back(position); prefer_move_back = should_move_back(position);
allocator_type &al = this->get_allocator_ref();
if(prefer_move_back){ if(prefer_move_back){
if(back_free_capacity()){ if(back_free_capacity()){
boost::container::expand_forward_and_insert_nonempty_middle_alloc boost::container::expand_forward_and_insert_nonempty_middle_alloc
( get_allocator_ref() ( al
, boost::movelib::to_raw_pointer(nonconst_pos) , boost::movelib::to_raw_pointer(nonconst_pos)
, this->priv_raw_end() , this->priv_raw_end()
, 1, proxy_t(::boost::forward<Args>(args)...)); , 1, proxy_t(::boost::forward<Args>(args)...));
@@ -1773,7 +1776,7 @@ class devector
else{ else{
if (front_free_capacity()){ if (front_free_capacity()){
boost::container::expand_backward_and_insert_nonempty_middle_alloc boost::container::expand_backward_and_insert_nonempty_middle_alloc
(get_allocator_ref() (al
, this->priv_raw_begin() , this->priv_raw_begin()
, boost::movelib::to_raw_pointer(nonconst_pos) , boost::movelib::to_raw_pointer(nonconst_pos)
, 1, proxy_t(::boost::forward<Args>(args)...)); , 1, proxy_t(::boost::forward<Args>(args)...));
@@ -1818,11 +1821,12 @@ class devector
else{\ else{\
iterator nonconst_pos = unconst_iterator(position);\ iterator nonconst_pos = unconst_iterator(position);\
prefer_move_back = should_move_back(position);\ prefer_move_back = should_move_back(position);\
allocator_type &al = this->get_allocator_ref();\
\ \
if(prefer_move_back){\ if(prefer_move_back){\
if(back_free_capacity()){\ if(back_free_capacity()){\
boost::container::expand_forward_and_insert_nonempty_middle_alloc\ boost::container::expand_forward_and_insert_nonempty_middle_alloc\
( get_allocator_ref()\ ( al\
, boost::movelib::to_raw_pointer(nonconst_pos)\ , boost::movelib::to_raw_pointer(nonconst_pos)\
, this->priv_raw_end()\ , this->priv_raw_end()\
, 1, proxy_t(BOOST_MOVE_FWD##N));\ , 1, proxy_t(BOOST_MOVE_FWD##N));\
@@ -1833,7 +1837,7 @@ class devector
else{\ else{\
if (front_free_capacity()){\ if (front_free_capacity()){\
boost::container::expand_backward_and_insert_nonempty_middle_alloc\ boost::container::expand_backward_and_insert_nonempty_middle_alloc\
(get_allocator_ref()\ (al\
, this->priv_raw_begin()\ , this->priv_raw_begin()\
, boost::movelib::to_raw_pointer(nonconst_pos)\ , boost::movelib::to_raw_pointer(nonconst_pos)\
, 1, proxy_t(BOOST_MOVE_FWD##N));\ , 1, proxy_t(BOOST_MOVE_FWD##N));\
@@ -2076,13 +2080,11 @@ class devector
size_type back_distance = size_type(end() - first); size_type back_distance = size_type(end() - first);
size_type n = boost::container::iterator_udistance(first, last); size_type n = boost::container::iterator_udistance(first, last);
if (front_distance < back_distance) if (front_distance < back_distance) {
{
// move n to the right // move n to the right
boost::container::move_backward(begin(), first, last); boost::container::move_backward(begin(), first, last);
for (iterator i = begin(); i != begin() + n; ++i) for (iterator i = begin(); i != begin() + n; ++i) {
{
allocator_traits_type::destroy(get_allocator_ref(), boost::movelib::to_raw_pointer(i)); allocator_traits_type::destroy(get_allocator_ref(), boost::movelib::to_raw_pointer(i));
} }
//n is always less than max stored_size_type //n is always less than max stored_size_type
@@ -2406,31 +2408,6 @@ class devector
return growth_factor_type()( size_type(m_.capacity), min_additional_cap, max); return growth_factor_type()( size_type(m_.capacity), min_additional_cap, max);
} }
void buffer_move_or_copy(pointer dst)
{
detail::construction_guard<allocator_type> guard(dst, get_allocator_ref());
buffer_move_or_copy(dst, guard);
guard.release();
}
void buffer_move_or_copy(pointer dst, detail::construction_guard<allocator_type>& guard)
{
opt_move_or_copy(begin(), end(), dst, guard);
destroy_elements(data(), data() + size());
deallocate_buffer();
}
template <typename Guard>
void opt_move_or_copy(pointer b, pointer e, pointer dst, Guard& guard)
{
// if trivial copy and default allocator, memcpy
boost::container::uninitialized_move_alloc(get_allocator_ref(), b, e, dst);
guard.extend();
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <typename... Args> template <typename... Args>
@@ -2497,18 +2474,25 @@ class devector
template <typename... Args> template <typename... Args>
void resize_front_slow_path(size_type sz, size_type n, Args&&... args) void resize_front_slow_path(size_type sz, size_type n, Args&&... args)
{ {
const size_type new_capacity = calculate_new_capacity(sz + back_free_capacity()); const size_type back_free_cap = back_free_capacity();
const size_type new_capacity = calculate_new_capacity(sz + back_free_cap);
pointer new_buffer = allocate(new_capacity); pointer new_buffer = allocate(new_capacity);
allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());
const size_type old_sz = this->size(); allocator_type &al = this->get_allocator_ref();
const size_type new_old_elem_index = new_capacity - old_sz; allocation_guard new_buffer_guard(new_buffer, new_capacity, al);
const size_type new_old_elem_index = new_capacity - this->size() - back_free_cap;
const size_type new_elem_index = new_old_elem_index - n; const size_type new_elem_index = new_old_elem_index - n;
detail::construction_guard<allocator_type> guard(new_buffer + new_elem_index, get_allocator_ref()); detail::construction_guard<allocator_type> guard(new_buffer + new_elem_index, al);
guarded_construct_n(new_buffer + new_elem_index, n, guard, boost::forward<Args>(args)...); guarded_construct_n(new_buffer + new_elem_index, n, guard, boost::forward<Args>(args)...);
buffer_move_or_copy(new_buffer + new_old_elem_index, guard); //This might throw
boost::container::uninitialized_move_alloc(al, begin(), end(), new_buffer + new_old_elem_index);
//This can't throw
this->destroy_elements(data(), data() + size());
this->deallocate_buffer();
guard.release(); guard.release();
new_buffer_guard.release(); new_buffer_guard.release();
@@ -2516,7 +2500,7 @@ class devector
m_.buffer = new_buffer; m_.buffer = new_buffer;
m_.set_capacity(new_capacity); m_.set_capacity(new_capacity);
m_.set_front_idx(new_elem_index); m_.set_front_idx(new_elem_index);
m_.set_back_idx(new_elem_index + old_sz + n); m_.set_back_idx(new_elem_index + sz);
} }
template <typename... Args> template <typename... Args>
@@ -2551,12 +2535,19 @@ class devector
{ {
const size_type new_capacity = calculate_new_capacity(sz + front_free_capacity()); const size_type new_capacity = calculate_new_capacity(sz + front_free_capacity());
pointer new_buffer = allocate(new_capacity); pointer new_buffer = allocate(new_capacity);
allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());
detail::construction_guard<allocator_type> guard(new_buffer + m_.back_idx, get_allocator_ref()); allocator_type &al = this->get_allocator_ref();
allocation_guard new_buffer_guard(new_buffer, new_capacity, al);
detail::construction_guard<allocator_type> guard(new_buffer + m_.back_idx, al);
guarded_construct_n(new_buffer + m_.back_idx, n, guard, boost::forward<Args>(args)...); guarded_construct_n(new_buffer + m_.back_idx, n, guard, boost::forward<Args>(args)...);
buffer_move_or_copy(new_buffer + m_.front_idx); //This might throw
boost::container::uninitialized_move_alloc(al, begin(), end(), new_buffer + m_.front_idx);
//This can't throw
this->destroy_elements(data(), data() + size());
this->deallocate_buffer();
guard.release(); guard.release();
new_buffer_guard.release(); new_buffer_guard.release();
@@ -2595,24 +2586,30 @@ class devector
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
void resize_front_slow_path(size_type sz, size_type n BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ void resize_front_slow_path(size_type sz, size_type n BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\ {\
const size_type new_capacity = calculate_new_capacity(sz + back_free_capacity());\ const size_type back_free_cap = back_free_capacity();\
const size_type new_capacity = calculate_new_capacity(sz + back_free_cap);\
pointer new_buffer = allocate(new_capacity);\ pointer new_buffer = allocate(new_capacity);\
allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());\ allocator_type &al = this->get_allocator_ref();\
\ allocation_guard new_buffer_guard(new_buffer, new_capacity, al);\
const size_type new_old_elem_index = new_capacity - size();\ \
const size_type new_old_elem_index = new_capacity - size() - back_free_cap;\
const size_type new_elem_index = new_old_elem_index - n;\ const size_type new_elem_index = new_old_elem_index - n;\
\ \
detail::construction_guard<allocator_type> guard(new_buffer + new_elem_index, get_allocator_ref());\ detail::construction_guard<allocator_type> guard(new_buffer + new_elem_index, al);\
guarded_construct_n(new_buffer + new_elem_index, n, guard BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ guarded_construct_n(new_buffer + new_elem_index, n, guard BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
\ \
buffer_move_or_copy(new_buffer + new_old_elem_index, guard);\ boost::container::uninitialized_move_alloc(al, begin(), end(), new_buffer + new_old_elem_index);\
\ \
guard.release();\ guard.release();\
new_buffer_guard.release();\ new_buffer_guard.release();\
\
this->destroy_elements(data(), data() + size());\
this->deallocate_buffer();\
\
m_.buffer = new_buffer;\ m_.buffer = new_buffer;\
m_.set_capacity(new_capacity);\ m_.set_capacity(new_capacity);\
m_.set_back_idx(new_old_elem_index + m_.back_idx - m_.front_idx);\
m_.set_front_idx(new_elem_index);\ m_.set_front_idx(new_elem_index);\
m_.set_back_idx(new_elem_index + sz);\
}\ }\
\ \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
@@ -2646,12 +2643,16 @@ class devector
{\ {\
const size_type new_capacity = calculate_new_capacity(sz + front_free_capacity());\ const size_type new_capacity = calculate_new_capacity(sz + front_free_capacity());\
pointer new_buffer = allocate(new_capacity);\ pointer new_buffer = allocate(new_capacity);\
allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());\ allocator_type &al = this->get_allocator_ref();\
allocation_guard new_buffer_guard(new_buffer, new_capacity, al);\
\ \
detail::construction_guard<allocator_type> guard(new_buffer + m_.back_idx, get_allocator_ref());\ detail::construction_guard<allocator_type> guard(new_buffer + m_.back_idx, al);\
guarded_construct_n(new_buffer + m_.back_idx, n, guard BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ guarded_construct_n(new_buffer + m_.back_idx, n, guard BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
\ \
buffer_move_or_copy(new_buffer + m_.front_idx);\ boost::container::uninitialized_move_alloc(al, begin(), end(), new_buffer + m_.front_idx);\
\
this->destroy_elements(data(), data() + size());\
this->deallocate_buffer();\
\ \
guard.release();\ guard.release();\
new_buffer_guard.release();\ new_buffer_guard.release();\
@@ -2671,8 +2672,9 @@ class devector
{ {
pointer new_buffer = allocate(new_capacity); pointer new_buffer = allocate(new_capacity);
{ {
allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref()); allocator_type &al = this->get_allocator_ref();
boost::container::uninitialized_move_alloc(get_allocator_ref(), this->begin(), this->end(), new_buffer + buffer_offset); allocation_guard new_buffer_guard(new_buffer, new_capacity, al);
boost::container::uninitialized_move_alloc(al, this->begin(), this->end(), new_buffer + buffer_offset);
new_buffer_guard.release(); new_buffer_guard.release();
} }
this->destroy_elements(m_.buffer + m_.front_idx, m_.buffer + m_.back_idx); this->destroy_elements(m_.buffer + m_.front_idx, m_.buffer + m_.back_idx);
@@ -2696,6 +2698,8 @@ class devector
size_type const n = boost::container::iterator_udistance(first, last); size_type const n = boost::container::iterator_udistance(first, last);
bool prefer_move_back; bool prefer_move_back;
allocator_type &al = this->get_allocator_ref();
if (BOOST_UNLIKELY(!n)) { if (BOOST_UNLIKELY(!n)) {
return begin() + size_type(position - cbegin()); return begin() + size_type(position - cbegin());
} }
@@ -2703,7 +2707,7 @@ class devector
if(back_free_capacity() >= n) // fast path if(back_free_capacity() >= n) // fast path
{ {
iterator r(this->end()); iterator r(this->end());
boost::container::uninitialized_copy_alloc(get_allocator_ref(), first, last, this->priv_raw_end()); boost::container::uninitialized_copy_alloc(al, first, last, this->priv_raw_end());
m_.set_back_idx(m_.back_idx + n); m_.set_back_idx(m_.back_idx + n);
return r; return r;
} }
@@ -2711,7 +2715,7 @@ class devector
} }
else if (position == begin()) { else if (position == begin()) {
if(front_free_capacity() >= n) {// secondary fast path if(front_free_capacity() >= n) {// secondary fast path
boost::container::uninitialized_copy_alloc(get_allocator_ref(), first, last, this->priv_raw_begin() - n); boost::container::uninitialized_copy_alloc(al, first, last, this->priv_raw_begin() - n);
m_.set_front_idx(m_.front_idx - n); m_.set_front_idx(m_.front_idx - n);
return begin(); return begin();
} }
@@ -2724,7 +2728,7 @@ class devector
if(prefer_move_back){ if(prefer_move_back){
if(back_free_capacity() >= n){ if(back_free_capacity() >= n){
boost::container::expand_forward_and_insert_nonempty_middle_alloc boost::container::expand_forward_and_insert_nonempty_middle_alloc
( get_allocator_ref() ( al
, boost::movelib::to_raw_pointer(nonconst_pos) , boost::movelib::to_raw_pointer(nonconst_pos)
, this->priv_raw_end() , this->priv_raw_end()
, n, proxy_t(first)); , n, proxy_t(first));
@@ -2735,7 +2739,7 @@ class devector
else{ else{
if (front_free_capacity() >= n){ if (front_free_capacity() >= n){
boost::container::expand_backward_and_insert_nonempty_middle_alloc boost::container::expand_backward_and_insert_nonempty_middle_alloc
( get_allocator_ref() ( al
, this->priv_raw_begin() , this->priv_raw_begin()
, boost::movelib::to_raw_pointer(nonconst_pos) , boost::movelib::to_raw_pointer(nonconst_pos)
, n, proxy_t(first)); , n, proxy_t(first));
@@ -2757,6 +2761,8 @@ class devector
size_type const index = size_type(p - cbegin()); size_type const index = size_type(p - cbegin());
size_type const cap = m_.capacity; size_type const cap = m_.capacity;
allocator_type &al = this->get_allocator_ref();
//Test if enough free memory would be left //Test if enough free memory would be left
if (free_cap >= n && (free_cap - n) >= cap/devector_min_free_fraction) { if (free_cap >= n && (free_cap - n) >= cap/devector_min_free_fraction) {
size_type const old_size = this->size(); size_type const old_size = this->size();
@@ -2769,7 +2775,7 @@ class devector
m_.back_idx = 0u; m_.back_idx = 0u;
m_.front_idx = 0u; m_.front_idx = 0u;
boost::container::expand_backward_forward_and_insert_alloc boost::container::expand_backward_forward_and_insert_alloc
(raw_beg, old_size, new_raw_beg, raw_pos, n, proxy, get_allocator_ref()); (raw_beg, old_size, new_raw_beg, raw_pos, n, proxy, al);
m_.set_front_idx(new_front_idx); m_.set_front_idx(new_front_idx);
m_.set_back_idx(new_front_idx + new_size); m_.set_back_idx(new_front_idx + new_size);
} }
@@ -2779,7 +2785,7 @@ class devector
pointer new_buffer = allocate(new_capacity); pointer new_buffer = allocate(new_capacity);
// guard allocation // guard allocation
allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref()); allocation_guard new_buffer_guard(new_buffer, new_capacity, al);
size_type const old_size = this->size(); size_type const old_size = this->size();
const size_type new_front_index = (new_capacity - old_size - n) / 2u; const size_type new_front_index = (new_capacity - old_size - n) / 2u;
@@ -2788,7 +2794,7 @@ class devector
T* const raw_new_start = const_cast<T*>(boost::movelib::to_raw_pointer(new_buffer)) + new_front_index; T* const raw_new_start = const_cast<T*>(boost::movelib::to_raw_pointer(new_buffer)) + new_front_index;
boost::container::uninitialized_move_and_insert_alloc boost::container::uninitialized_move_and_insert_alloc
(get_allocator_ref(), this->priv_raw_begin(), raw_pos, this->priv_raw_end(), raw_new_start, n, proxy); (al, this->priv_raw_begin(), raw_pos, this->priv_raw_end(), raw_new_start, n, proxy);
new_buffer_guard.release(); new_buffer_guard.release();
// cleanup // cleanup
@@ -2819,8 +2825,9 @@ class devector
size_type n = boost::container::iterator_udistance(first, last); size_type n = boost::container::iterator_udistance(first, last);
pointer new_buffer = n ? allocate(n) : pointer(); pointer new_buffer = n ? allocate(n) : pointer();
allocation_guard new_buffer_guard(new_buffer, n, get_allocator_ref()); allocator_type &al = this->get_allocator_ref();
boost::container::uninitialized_copy_alloc(get_allocator_ref(), first, last, new_buffer); allocation_guard new_buffer_guard(new_buffer, n, al);
boost::container::uninitialized_copy_alloc(al, first, last, new_buffer);
this->destroy_elements(begin(), end()); this->destroy_elements(begin(), end());
this->deallocate_buffer(); this->deallocate_buffer();
@@ -2855,7 +2862,8 @@ class devector
InputIterator overwrite_buffer_impl(InputIterator first, InputIterator last, dtl::false_) InputIterator overwrite_buffer_impl(InputIterator first, InputIterator last, dtl::false_)
{ {
pointer pos = m_.buffer; pointer pos = m_.buffer;
detail::construction_guard<allocator_type> front_guard(pos, get_allocator_ref()); allocator_type &al = this->get_allocator_ref();
detail::construction_guard<allocator_type> front_guard(pos, al);
while (first != last && pos != begin()) { while (first != last && pos != begin()) {
this->alloc_construct(pos++, *first++); this->alloc_construct(pos++, *first++);
@@ -2866,7 +2874,7 @@ class devector
*pos++ = *first++; *pos++ = *first++;
} }
detail::construction_guard<allocator_type> back_guard(pos, get_allocator_ref()); detail::construction_guard<allocator_type> back_guard(pos, al);
iterator capacity_end = m_.buffer + m_.capacity; iterator capacity_end = m_.buffer + m_.capacity;
while (first != last && pos != capacity_end) { while (first != last && pos != capacity_end) {