diff options
author | Lars Knoll <lars.knoll@qt.io> | 2020-11-04 22:59:09 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2020-11-17 11:45:46 +0100 |
commit | 6be39809b038768a665b0e29a3a3668fdc424d9a (patch) | |
tree | 51b29213d4beed589e89a6bcae34874d5f63c593 /src/corelib/tools/qarraydatapointer.h | |
parent | 20883c9bcc7882b79db438ed0959530f82c8ee0a (diff) |
Simplify reallocation handling in QList
Have one generic method for detaching and reallocations.
Use that method throughout QList to avoid duplicated
instantiations of code paths that are rarely used.
Change-Id: I5b9add3be5f17b387e2d34028b72c8f52db68444
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/tools/qarraydatapointer.h')
-rw-r--r-- | src/corelib/tools/qarraydatapointer.h | 88 |
1 files changed, 46 insertions, 42 deletions
diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h index 26e8f934ee..1aa9a670e7 100644 --- a/src/corelib/tools/qarraydatapointer.h +++ b/src/corelib/tools/qarraydatapointer.h @@ -162,17 +162,55 @@ public: swap(tmp); } - QArrayDataPointer detach() + void detach(QArrayDataPointer *old = nullptr) { - if (needsDetach()) { - QPair<Data *, T *> copy = clone(); - QArrayDataPointer old(d, ptr, size); - d = copy.first; - ptr = copy.second; - return old; + if (needsDetach()) + reallocateAndGrow(QArrayData::GrowsAtEnd, 0, old); + } + + // pass in a pointer to a default constructed QADP, to keep it alive beyond the detach() call + void detachAndGrow(QArrayData::GrowthPosition where, qsizetype n, QArrayDataPointer *old = nullptr) + { + if (!needsDetach()) { + if (!n || + (where == QArrayData::GrowsAtBeginning && freeSpaceAtBegin() >= n) || + (where == QArrayData::GrowsAtEnd && freeSpaceAtEnd() >= n)) + return; + } + reallocateAndGrow(where, n, old); + } + + Q_NEVER_INLINE void reallocateAndGrow(QArrayData::GrowthPosition where, qsizetype n, QArrayDataPointer *old = nullptr) + { + if constexpr (QTypeInfo<T>::isRelocatable && alignof(T) <= alignof(std::max_align_t)) { + if (where == QArrayData::GrowsAtEnd && !old && !needsDetach() && n > 0) { + (*this)->reallocate(constAllocatedCapacity() - freeSpaceAtEnd() + n, QArrayData::Grow); // fast path + return; + } + } + + QArrayDataPointer dp(allocateGrow(*this, n, where)); + if (where == QArrayData::GrowsAtBeginning) { + dp.ptr += n; + Q_ASSERT(dp.freeSpaceAtBegin() >= n); + } else { + Q_ASSERT(dp.freeSpaceAtEnd() >= n); + } + if (size) { + qsizetype toCopy = size; + if (n < 0) + toCopy += n; + if (needsDetach() || old) + dp->copyAppend(begin(), begin() + toCopy); + else + dp->moveAppend(begin(), begin() + toCopy); + dp.d->flags = flags(); + Q_ASSERT(dp.size == toCopy); } - return QArrayDataPointer(); + swap(dp); + if (old) + old->swap(dp); } // forwards from QArrayData @@ -244,40 +282,6 @@ public: return lhs.data() != rhs.data() || lhs.size != rhs.size; } - static void reallocateGrow(QArrayDataPointer &from, qsizetype n) - { - Q_ASSERT(n > 0); - - if constexpr (!QTypeInfo<T>::isRelocatable || alignof(T) > alignof(std::max_align_t)) { - QArrayDataPointer dd(allocateGrow(from, n, QArrayData::GrowsAtEnd)); - dd->copyAppend(from.data(), from.data() + from.size); - from.swap(dd); - } else { - if (from.needsDetach()) { - QArrayDataPointer dd(allocateGrow(from, n, QArrayData::GrowsAtEnd)); - dd->copyAppend(from.data(), from.data() + from.size); - from.swap(dd); - } else { - from->reallocate(from.constAllocatedCapacity() - from.freeSpaceAtEnd() + n, QArrayData::Grow); // fast path - } - } - } - -private: - [[nodiscard]] QPair<Data *, T *> clone() const - { - QPair<Data *, T *> pair = Data::allocate(detachCapacity(size), QArrayData::KeepSize); - QArrayDataPointer copy(pair.first, pair.second, 0); - if (size) - copy->copyAppend(begin(), end()); - - if (pair.first) - pair.first->flags = flags(); - copy.d = nullptr; - copy.ptr = nullptr; - return pair; - } - protected: Data *d; T *ptr; |