From 460700f7736ae308bcbaa37f512355d09876dc8b Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Fri, 25 Jun 2021 11:06:30 +0200 Subject: 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 --- src/corelib/kernel/qcoreapplication.cpp | 2 ++ src/corelib/kernel/qproperty.cpp | 15 ++++++++++++++- src/corelib/kernel/qproperty.h | 1 + src/corelib/kernel/qproperty_p.h | 1 + 4 files changed, 18 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 812b4afcc4..87ab87181f 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -47,6 +47,7 @@ #include "qeventloop.h" #endif #include "qmetaobject.h" +#include #include "qcorecmdlineargs_p.h" #include #include @@ -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(qtHookData[QHooks::Startup])(); #endif diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index f1c8adb8a0..50ec3807d3 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -43,6 +43,7 @@ #include #include #include +#include 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(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; diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h index b25e932595..008748840d 100644 --- a/src/corelib/kernel/qproperty.h +++ b/src/corelib/kernel/qproperty.h @@ -943,6 +943,7 @@ struct QBindingStatus { QtPrivate::BindingEvaluationState *currentlyEvaluatingBinding = nullptr; QtPrivate::CompatPropertySafePoint *currentCompatProperty = nullptr; + Qt::HANDLE threadId = nullptr; }; struct QBindingStorageData; diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h index 2883308299..ba1eb7adf2 100644 --- a/src/corelib/kernel/qproperty_p.h +++ b/src/corelib/kernel/qproperty_p.h @@ -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 -- cgit v1.2.3