QProperty: Avoid TLS lookup if we are in the same thread
If the QBindingStatus we receive from the QObject is from the thread which is currently running, we do not need to refetch the thread local; the reason we refetched the thread_local was after all only to guard against the case where a QObject's property gets read in a different thread. To determine whether we are in the same thread, we can store the thread id in the thread_local structure. Currently, it only gets initialized for the main thread in QCoreApplication (as bindings are mostly used there). At a later point, we could either expose initBindingStatusThreadId, or call the function when a QThread gets started. Pick-to: 6.2 Change-Id: Id8eb803973bb083abfab83a62bfccc9e88a4e542 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
fa8cffa4c9
commit
460700f773
@ -47,6 +47,7 @@
|
||||
#include "qeventloop.h"
|
||||
#endif
|
||||
#include "qmetaobject.h"
|
||||
#include <private/qproperty_p.h>
|
||||
#include "qcorecmdlineargs_p.h"
|
||||
#include <qdatastream.h>
|
||||
#include <qdebug.h>
|
||||
@ -861,6 +862,7 @@ void QCoreApplicationPrivate::init()
|
||||
qt_call_pre_routines();
|
||||
qt_startup_hook();
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
QtPrivate::initBindingStatusThreadId();
|
||||
if (Q_UNLIKELY(qtHookData[QHooks::Startup]))
|
||||
reinterpret_cast<QHooks::StartupCallback>(qtHookData[QHooks::Startup])();
|
||||
#endif
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include <qscopedvaluerollback.h>
|
||||
#include <QScopeGuard>
|
||||
#include <QtCore/qloggingcategory.h>
|
||||
#include <QThread>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -2184,7 +2185,12 @@ void QBindingStorage::registerDependency_helper(const QUntypedPropertyData *data
|
||||
Q_ASSERT(bindingStatus);
|
||||
// Use ::bindingStatus to get the binding from TLS. This is required, so that reads from
|
||||
// another thread do not register as dependencies
|
||||
auto *currentBinding = QT_PREPEND_NAMESPACE(bindingStatus).currentlyEvaluatingBinding;
|
||||
const bool threadMatches = (QThread::currentThreadId() == bindingStatus->threadId);
|
||||
QtPrivate::BindingEvaluationState *currentBinding;
|
||||
if (Q_LIKELY(threadMatches))
|
||||
currentBinding = bindingStatus->currentlyEvaluatingBinding;
|
||||
else
|
||||
currentBinding = QT_PREPEND_NAMESPACE(bindingStatus).currentlyEvaluatingBinding;
|
||||
QUntypedPropertyData *dd = const_cast<QUntypedPropertyData *>(data);
|
||||
auto storage = QBindingStoragePrivate(d).get(dd, /*create=*/ currentBinding != nullptr);
|
||||
if (!storage)
|
||||
@ -2205,6 +2211,13 @@ QPropertyBindingData *QBindingStorage::bindingData_helper(QUntypedPropertyData *
|
||||
|
||||
|
||||
namespace QtPrivate {
|
||||
|
||||
|
||||
void initBindingStatusThreadId()
|
||||
{
|
||||
bindingStatus.threadId = QThread::currentThreadId();
|
||||
}
|
||||
|
||||
BindingEvaluationState *suspendCurrentBindingStatus()
|
||||
{
|
||||
auto ret = bindingStatus.currentlyEvaluatingBinding;
|
||||
|
@ -943,6 +943,7 @@ struct QBindingStatus
|
||||
{
|
||||
QtPrivate::BindingEvaluationState *currentlyEvaluatingBinding = nullptr;
|
||||
QtPrivate::CompatPropertySafePoint *currentCompatProperty = nullptr;
|
||||
Qt::HANDLE threadId = nullptr;
|
||||
};
|
||||
|
||||
struct QBindingStorageData;
|
||||
|
@ -391,6 +391,7 @@ inline QPropertyObserverPointer QPropertyBindingDataPointer::firstObserver() con
|
||||
|
||||
namespace QtPrivate {
|
||||
Q_CORE_EXPORT bool isPropertyInBindingWrapper(const QUntypedPropertyData *property);
|
||||
void Q_CORE_EXPORT initBindingStatusThreadId();
|
||||
}
|
||||
|
||||
template<typename Class, typename T, auto Offset, auto Setter, auto Signal=nullptr>
|
||||
|
Loading…
x
Reference in New Issue
Block a user