QVLA: separate control from inline storage [5/N]: Move reallocate()

This is the core of QVarLengthArray. To move it down into QVLABase, we
need to pass Prealloc and this->array as additional function
arguments.

Task-number: QTBUG-84785
Change-Id: I082fa4ef957fcde7b8fcc3ca421621aa01ba5d59
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Marc Mutz 2021-11-30 16:35:06 +01:00
parent e01f3e8b5a
commit 61be5c94ed

View File

@ -205,6 +205,8 @@ protected:
return std::lexicographical_compare(begin(), end(), other.begin(), other.end()); return std::lexicographical_compare(begin(), end(), other.begin(), other.end());
} }
void reallocate_impl(qsizetype prealloc, void *array, qsizetype size, qsizetype alloc);
bool isValidIterator(const const_iterator &i) const bool isValidIterator(const const_iterator &i) const
{ {
const std::less<const T *> less = {}; const std::less<const T *> less = {};
@ -579,7 +581,8 @@ private:
bool less_than(const QVarLengthArray<U, Prealloc2> &other) const bool less_than(const QVarLengthArray<U, Prealloc2> &other) const
{ return Base::less_than(other); } { return Base::less_than(other); }
void reallocate(qsizetype size, qsizetype alloc); void reallocate(qsizetype sz, qsizetype alloc)
{ Base::reallocate_impl(Prealloc, this->array, sz, alloc); }
using Base::isValidIterator; using Base::isValidIterator;
}; };
@ -678,8 +681,8 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::append(const T *abuf, qs
this->s = asize; this->s = asize;
} }
template <class T, qsizetype Prealloc> template <class T>
Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::reallocate(qsizetype asize, qsizetype aalloc) Q_OUTOFLINE_TEMPLATE void QVLABase<T>::reallocate_impl(qsizetype prealloc, void *array, qsizetype asize, qsizetype aalloc)
{ {
Q_ASSERT(aalloc >= asize); Q_ASSERT(aalloc >= asize);
Q_ASSERT(data()); Q_ASSERT(data());
@ -696,24 +699,24 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::reallocate(qsizetype asi
std::unique_ptr<void, free_deleter> guard; std::unique_ptr<void, free_deleter> guard;
void *newPtr; void *newPtr;
qsizetype newA; qsizetype newA;
if (aalloc > Prealloc) { if (aalloc > prealloc) {
newPtr = malloc(aalloc * sizeof(T)); newPtr = malloc(aalloc * sizeof(T));
guard.reset(newPtr); guard.reset(newPtr);
Q_CHECK_PTR(newPtr); // could throw Q_CHECK_PTR(newPtr); // could throw
// by design: in case of QT_NO_EXCEPTIONS malloc must not fail or it crashes here // by design: in case of QT_NO_EXCEPTIONS malloc must not fail or it crashes here
newA = aalloc; newA = aalloc;
} else { } else {
newPtr = this->array; newPtr = array;
newA = Prealloc; newA = prealloc;
} }
QtPrivate::q_uninitialized_relocate_n(oldPtr, copySize, QtPrivate::q_uninitialized_relocate_n(oldPtr, copySize,
reinterpret_cast<T *>(newPtr)); reinterpret_cast<T *>(newPtr));
// commit: // commit:
this->ptr = newPtr; ptr = newPtr;
guard.release(); guard.release();
this->a = newA; a = newA;
} }
this->s = copySize; s = copySize;
// destroy remaining old objects // destroy remaining old objects
if constexpr (QTypeInfo<T>::isComplex) { if constexpr (QTypeInfo<T>::isComplex) {
@ -721,17 +724,17 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::reallocate(qsizetype asi
std::destroy(oldPtr + asize, oldPtr + osize); std::destroy(oldPtr + asize, oldPtr + osize);
} }
if (oldPtr != reinterpret_cast<T *>(this->array) && oldPtr != data()) if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != data())
free(oldPtr); free(oldPtr);
if constexpr (QTypeInfo<T>::isComplex) { if constexpr (QTypeInfo<T>::isComplex) {
// call default constructor for new objects (which can throw) // call default constructor for new objects (which can throw)
while (size() < asize) { while (size() < asize) {
new (data() + size()) T; new (data() + size()) T;
++this->s; ++s;
} }
} else { } else {
this->s = asize; s = asize;
} }
} }