summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qthread_p.h
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2022-02-24 09:03:26 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2022-03-10 07:21:11 +0100
commitba6c1d2785ca6d8a8b162abcd9d978ab0c52ea2d (patch)
treee1417c0d76903800fa4d869f419fa574aa285501 /src/corelib/thread/qthread_p.h
parent64ffe0aacb6bba4875a9ccdeea96b5858c7d01e6 (diff)
QProperty: fix threading issues
QObject's cache the binding status pointer to avoid TLS lookups. However, when an object is moved to a different thread, we need to update the cached pointer (as the original thread might stop and thus no longer exist, and to correctly allow setting up bindings in the object's thread). Fix this by also storing the binding status in QThreadPrivate and updating the object's binding status when moved. This does only work when the thread is already running, though. If it is not running, we instead treat the QThreadPrivate's status pointer as a pointer to a vector of pending objects. Once the QThread has been started, we check if there are pending objects, and update them at this point. Pick-to: 6.2 6.3 Fixes: QTBUG-101177 Change-Id: I0490bbbdc1a17cb5f85044ad6eb2e1a8c759d4b7 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/corelib/thread/qthread_p.h')
-rw-r--r--src/corelib/thread/qthread_p.h33
1 files changed, 33 insertions, 0 deletions
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index aa6183f7e2..a895b37b29 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -202,6 +202,34 @@ public:
}
}
+ QBindingStatus *bindingStatus()
+ {
+ auto statusOrPendingObjects = m_statusOrPendingObjects.loadAcquire();
+ if (!(statusOrPendingObjects & 1))
+ return (QBindingStatus *) statusOrPendingObjects;
+ return nullptr;
+ }
+
+ void addObjectWithPendingBindingStatusChange(QObject *obj)
+ {
+ Q_ASSERT(!bindingStatus());
+ auto pendingObjects = pendingObjectsWithBindingStatusChange();
+ if (!pendingObjects) {
+ pendingObjects = new std::vector<QObject *>();
+ m_statusOrPendingObjects = quintptr(pendingObjects) | 1;
+ }
+ pendingObjects->push_back(obj);
+ }
+
+ std::vector<QObject *> *pendingObjectsWithBindingStatusChange()
+ {
+ auto statusOrPendingObjects = m_statusOrPendingObjects.loadAcquire();
+ if (statusOrPendingObjects & 1)
+ return reinterpret_cast<std::vector<QObject *> *>(statusOrPendingObjects - 1);
+ return nullptr;
+ }
+
+ QAtomicInteger<quintptr> m_statusOrPendingObjects = 0;
#ifndef Q_OS_INTEGRITY
private:
// Used in QThread(Private)::start to avoid racy access to QObject::objectName,
@@ -220,8 +248,13 @@ public:
mutable QMutex mutex;
QThreadData *data;
+ QBindingStatus* m_bindingStatus;
bool running = false;
+ QBindingStatus* bindingStatus() { return m_bindingStatus; }
+ void addObjectWithPendingBindingStatusChange(QObject *) {}
+ std::vector<QObject *> * pendingObjectsWithBindingStatusChange() { return nullptr; }
+
static void setCurrentThread(QThread *) { }
static QAbstractEventDispatcher *createEventDispatcher(QThreadData *data);