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>
This commit is contained in:
parent
4447db4465
commit
dba6067670
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user