Skip to content

Commit

Permalink
Implement fast paths for removeFirst() and removeLast()
Browse files Browse the repository at this point in the history
This avoids lots of the code and checks in remove() making the
methods a lot faster.

Change-Id: If99c39f5b55672b341f9331b5903bf77e9e67477
Reviewed-by: Andrei Golubev <[email protected]>
Reviewed-by: Thiago Macieira <[email protected]>
  • Loading branch information
laknoll committed Nov 9, 2020
1 parent 13fcd02 commit f438286
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 2 deletions.
44 changes: 44 additions & 0 deletions src/corelib/tools/qarraydataops.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,19 @@ struct QPodArrayOps
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);
Expand Down Expand Up @@ -830,6 +843,22 @@ struct QGenericArrayOps
} 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);
Expand Down Expand Up @@ -1300,6 +1329,21 @@ struct QCommonArrayOps : QArrayOpsSelector<T>::Type
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
Expand Down
22 changes: 20 additions & 2 deletions src/corelib/tools/qlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,8 @@ class QList
}

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; }

Expand Down Expand Up @@ -655,8 +655,26 @@ inline void QList<T>::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 <typename T>
inline void QList<T>::removeFirst()
{
Q_ASSERT(!isEmpty());
if (d->needsDetach())
d.detach();
d->eraseFirst();
}

template <typename T>
inline void QList<T>::removeLast()
{
Q_ASSERT(!isEmpty());
if (d->needsDetach())
detach();
d->eraseLast();
}


template<typename T>
inline T QList<T>::value(qsizetype i, parameter_type defaultValue) const
{
Expand Down

0 comments on commit f438286

Please sign in to comment.