summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2018-10-25 16:35:58 -0700
committerThiago Macieira <thiago.macieira@intel.com>2018-11-28 04:37:10 +0000
commitdba606767056986a8c0cc973ec5932f603f14759 (patch)
treeaca909fa2fa06b984f54b8577c629b6068e892f0 /src/corelib/tools
parent4447db44652420d80886de8de4b02f3bcd9fe86c (diff)
Optimize QSharedPointer::getAndRef with the three-operand testAndSet
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 <romain.pokrzywka@gmail.com> Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@qt.io>
Diffstat (limited to 'src/corelib/tools')
-rw-r--r--src/corelib/tools/qsharedpointer.cpp11
1 files changed, 7 insertions, 4 deletions
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;
}
/**