From dba606767056986a8c0cc973ec5932f603f14759 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 25 Oct 2018 16:35:58 -0700 Subject: Optimize QSharedPointer::getAndRef with the three-operand testAndSet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Originally QAtomicPointer didn't have the three-operand version, resulting in code like: if (!atomic.testAndSetXxx(expected, newvalue)) expected = atomic.load(); The three-operand version gives us the current value of the atomic in case the test failed and it's free in all architectures, unlike the extra load. I have to use testAndSetOrdered here because I need the failing load to use the Acquire memory order, even though that has an extra Acquire for the successful case we don't need. QAtomicPointer does not have testAndSetReleaseAcquire. Change-Id: I1bd327aeaf73421a8ec5fffd1560fe30d3bfd9b8 Reviewed-by: Romain Pokrzywka Reviewed-by: Jędrzej Nowacki --- src/corelib/tools/qsharedpointer.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/corelib/tools/qsharedpointer.cpp') diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 622b03f42d..a1caeeb135 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -1383,15 +1383,18 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge ExternalRefCountData *x = new ExternalRefCountData(Qt::Uninitialized); x->strongref.store(-1); x->weakref.store(2); // the QWeakPointer that called us plus the QObject itself - if (!d->sharedRefcount.testAndSetRelease(0, x)) { + + ExternalRefCountData *ret; + if (d->sharedRefcount.testAndSetOrdered(nullptr, x, ret)) { // ought to be release+acquire; this is acq_rel+acquire + ret = x; + } else { // ~ExternalRefCountData has a Q_ASSERT, so we use this trick to // only execute this if Q_ASSERTs are enabled Q_ASSERT((x->weakref.store(0), true)); delete x; - x = d->sharedRefcount.loadAcquire(); - x->weakref.ref(); + ret->weakref.ref(); } - return x; + return ret; } /** -- cgit v1.2.3