cleanOrphanedConnectionsImpl: Allow to skip locking
This function is/will be used in a few places where we already have a lock. Temporarily unlocking and relocking invites all kinds of troubles. By adding a flag we can instead tell the function that we already hold the lock. Change-Id: Ibca089de61133661d5cd75290f2a55c22c5d013c Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> (cherry picked from commit 556fc646cfac4dca43a34f5c4a4f7e6e3ef9104d) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
32eb742b04
commit
b6323f0c7b
@ -70,6 +70,7 @@
|
||||
#include <qtcore_tracepoints_p.h>
|
||||
|
||||
#include <new>
|
||||
#include <mutex>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
@ -405,11 +406,14 @@ void QObjectPrivate::ConnectionData::removeConnection(QObjectPrivate::Connection
|
||||
|
||||
}
|
||||
|
||||
void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender)
|
||||
void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender, LockPolicy lockPolicy)
|
||||
{
|
||||
QBasicMutex *senderMutex = signalSlotLock(sender);
|
||||
ConnectionOrSignalVector *c = nullptr;
|
||||
{
|
||||
QBasicMutexLocker l(signalSlotLock(sender));
|
||||
std::unique_lock<QBasicMutex> lock(*senderMutex, std::defer_lock_t{});
|
||||
if (lockPolicy == NeedToLock)
|
||||
lock.lock();
|
||||
if (ref.loadAcquire() > 1)
|
||||
return;
|
||||
|
||||
@ -419,7 +423,16 @@ void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sende
|
||||
c = orphaned.loadRelaxed();
|
||||
orphaned.storeRelaxed(nullptr);
|
||||
}
|
||||
deleteOrphaned(c);
|
||||
if (c) {
|
||||
// Deleting c might run arbitrary user code, so we must not hold the lock
|
||||
if (lockPolicy == AlreadyLockedAndTemporarilyReleasingLock) {
|
||||
senderMutex->unlock();
|
||||
deleteOrphaned(c);
|
||||
senderMutex->lock();
|
||||
} else {
|
||||
deleteOrphaned(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectPrivate::ConnectionData::deleteOrphaned(QObjectPrivate::ConnectionOrSignalVector *o)
|
||||
|
@ -266,12 +266,19 @@ public:
|
||||
// must be called on the senders connection data
|
||||
// assumes the senders and receivers lock are held
|
||||
void removeConnection(Connection *c);
|
||||
void cleanOrphanedConnections(QObject *sender)
|
||||
enum LockPolicy {
|
||||
NeedToLock,
|
||||
// Beware that we need to temporarily release the lock
|
||||
// and thus calling code must carefully consider whether
|
||||
// invariants still hold.
|
||||
AlreadyLockedAndTemporarilyReleasingLock
|
||||
};
|
||||
void cleanOrphanedConnections(QObject *sender, LockPolicy lockPolicy = NeedToLock)
|
||||
{
|
||||
if (orphaned.loadRelaxed() && ref.loadAcquire() == 1)
|
||||
cleanOrphanedConnectionsImpl(sender);
|
||||
cleanOrphanedConnectionsImpl(sender, lockPolicy);
|
||||
}
|
||||
void cleanOrphanedConnectionsImpl(QObject *sender);
|
||||
void cleanOrphanedConnectionsImpl(QObject *sender, LockPolicy lockPolicy);
|
||||
|
||||
ConnectionList &connectionsForSignal(int signal)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user