diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2022-02-24 09:03:26 +0100 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2022-03-10 07:21:11 +0100 |
commit | ba6c1d2785ca6d8a8b162abcd9d978ab0c52ea2d (patch) | |
tree | e1417c0d76903800fa4d869f419fa574aa285501 /src/corelib/thread/qthread_p.h | |
parent | 64ffe0aacb6bba4875a9ccdeea96b5858c7d01e6 (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.h | 33 |
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); |