QMetaObject: Compare threadIds when checking receiver thread

Comparing threadIds is faster, especially if invoked from a non qt thread,
where QThread::currentThread() needs to create a QAdoptedThread/QThreadData first.

Pick-to: 5.15
Change-Id: I44b3013283754f1a5ac9d62debcf4c82be77c554
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Mike Achtelik 2020-06-15 10:08:14 +02:00
parent cb1c66bd20
commit 907027ab80

View File

@ -56,6 +56,7 @@
#include "private/qobject_p.h" #include "private/qobject_p.h"
#include "private/qmetaobject_p.h" #include "private/qmetaobject_p.h"
#include "private/qthread_p.h"
// for normalizeTypeInternal // for normalizeTypeInternal
#include "private/qmetaobject_moc_p.h" #include "private/qmetaobject_moc_p.h"
@ -1467,10 +1468,14 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
if (! object) if (! object)
return false; return false;
QThread *currentThread = QThread::currentThread(); Qt::HANDLE currentThreadId = QThread::currentThreadId();
QThread *objectThread = object->thread(); QThread *objectThread = object->thread();
bool receiverInSameThread = false;
if (objectThread)
receiverInSameThread = currentThreadId == QThreadData::get2(objectThread)->threadId.loadRelaxed();
if (type == Qt::AutoConnection) if (type == Qt::AutoConnection)
type = (currentThread == objectThread) ? Qt::DirectConnection : Qt::QueuedConnection; type = receiverInSameThread ? Qt::DirectConnection : Qt::QueuedConnection;
void *argv[] = { ret }; void *argv[] = { ret };
@ -1486,7 +1491,7 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
QCoreApplication::postEvent(object, new QMetaCallEvent(slot, nullptr, -1, 1)); QCoreApplication::postEvent(object, new QMetaCallEvent(slot, nullptr, -1, 1));
} else if (type == Qt::BlockingQueuedConnection) { } else if (type == Qt::BlockingQueuedConnection) {
#if QT_CONFIG(thread) #if QT_CONFIG(thread)
if (currentThread == objectThread) if (receiverInSameThread)
qWarning("QMetaObject::invokeMethod: Dead lock detected"); qWarning("QMetaObject::invokeMethod: Dead lock detected");
QSemaphore semaphore; QSemaphore semaphore;
@ -2253,11 +2258,15 @@ bool QMetaMethod::invoke(QObject *object,
if (paramCount <= QMetaMethodPrivate::get(this)->parameterCount()) if (paramCount <= QMetaMethodPrivate::get(this)->parameterCount())
return false; return false;
Qt::HANDLE currentThreadId = QThread::currentThreadId();
QThread *objectThread = object->thread();
bool receiverInSameThread = false;
if (objectThread)
receiverInSameThread = currentThreadId == QThreadData::get2(objectThread)->threadId.loadRelaxed();
// check connection type // check connection type
if (connectionType == Qt::AutoConnection) { if (connectionType == Qt::AutoConnection) {
QThread *currentThread = QThread::currentThread(); connectionType = receiverInSameThread
QThread *objectThread = object->thread();
connectionType = currentThread == objectThread
? Qt::DirectConnection ? Qt::DirectConnection
: Qt::QueuedConnection; : Qt::QueuedConnection;
} }
@ -2328,9 +2337,7 @@ bool QMetaMethod::invoke(QObject *object,
QCoreApplication::postEvent(object, event.take()); QCoreApplication::postEvent(object, event.take());
} else { // blocking queued connection } else { // blocking queued connection
#if QT_CONFIG(thread) #if QT_CONFIG(thread)
QThread *currentThread = QThread::currentThread(); if (receiverInSameThread) {
QThread *objectThread = object->thread();
if (currentThread == objectThread) {
qWarning("QMetaMethod::invoke: Dead lock detected in " qWarning("QMetaMethod::invoke: Dead lock detected in "
"BlockingQueuedConnection: Receiver is %s(%p)", "BlockingQueuedConnection: Receiver is %s(%p)",
mobj->className(), object); mobj->className(), object);