From f43828687581c2d89549225d1cdc7518bde43b65 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 4 Nov 2020 11:10:56 +0100 Subject: [PATCH] Implement fast paths for removeFirst() and removeLast() This avoids lots of the code and checks in remove() making the methods a lot faster. Change-Id: If99c39f5b55672b341f9331b5903bf77e9e67477 Reviewed-by: Andrei Golubev Reviewed-by: Thiago Macieira --- src/corelib/tools/qarraydataops.h | 44 +++++++++++++++++++++++++++++++ src/corelib/tools/qlist.h | 22 ++++++++++++++-- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h index 12d30e6d5d..fc9c5dbe7f 100644 --- a/src/corelib/tools/qarraydataops.h +++ b/src/corelib/tools/qarraydataops.h @@ -429,6 +429,19 @@ public: this->size -= (e - b); } + void eraseFirst() + { + Q_ASSERT(this->size); + ++this->ptr; + --this->size; + } + + void eraseLast() + { + Q_ASSERT(this->size); + --this->size; + } + void assign(T *b, T *e, parameter_type t) { Q_ASSERT(b <= e); @@ -830,6 +843,22 @@ public: } while (b != e); } + void eraseFirst() + { + Q_ASSERT(this->size); + this->begin()->~T(); + ++this->ptr; + --this->size; + } + + void eraseLast() + { + Q_ASSERT(this->size); + (--this->end())->~T(); + --this->size; + } + + void assign(T *b, T *e, parameter_type t) { Q_ASSERT(b <= e); @@ -1300,6 +1329,21 @@ public: Base::erase(GrowsForwardTag{}, b, e); } } + + void eraseFirst() + { + Q_ASSERT(this->isMutable()); + Q_ASSERT(this->size); + Base::eraseFirst(); + } + + void eraseLast() + { + Q_ASSERT(this->isMutable()); + Q_ASSERT(this->size); + Base::eraseLast(); + } + }; } // namespace QtPrivate diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index b4070a27fc..6fe3522f6f 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -377,8 +377,8 @@ public: } void remove(qsizetype i, qsizetype n = 1); - void removeFirst() { Q_ASSERT(!isEmpty()); remove(0); } - void removeLast() { Q_ASSERT(!isEmpty()); remove(size() - 1); } + void removeFirst(); + void removeLast(); value_type takeFirst() { Q_ASSERT(!isEmpty()); value_type v = std::move(first()); remove(0); return v; } value_type takeLast() { Q_ASSERT(!isEmpty()); value_type v = std::move(last()); remove(size() - 1); return v; } @@ -655,8 +655,26 @@ inline void QList::remove(qsizetype i, qsizetype n) // we're detached and we can just move data around d->erase(d->begin() + i, d->begin() + i + n); } + +template +inline void QList::removeFirst() +{ + Q_ASSERT(!isEmpty()); + if (d->needsDetach()) + d.detach(); + d->eraseFirst(); } +template +inline void QList::removeLast() +{ + Q_ASSERT(!isEmpty()); + if (d->needsDetach()) + detach(); + d->eraseLast(); +} + + template inline T QList::value(qsizetype i, parameter_type defaultValue) const {