diff options
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qbindingstorage.h | 8 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 28 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.h | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qproperty.cpp | 17 | ||||
-rw-r--r-- | src/corelib/kernel/qproperty_p.h | 1 |
6 files changed, 55 insertions, 5 deletions
diff --git a/src/corelib/kernel/qbindingstorage.h b/src/corelib/kernel/qbindingstorage.h index 2ffaf18adf..4f8b7bfc5e 100644 --- a/src/corelib/kernel/qbindingstorage.h +++ b/src/corelib/kernel/qbindingstorage.h @@ -65,6 +65,11 @@ struct QBindingStatus QPropertyDelayedNotifications *groupUpdateData = nullptr; }; +namespace QtPrivate { +struct QBindingStatusAccessToken; +Q_AUTOTEST_EXPORT QBindingStatus *getBindingStatus(QBindingStatusAccessToken); +} + struct QBindingStorageData; class Q_CORE_EXPORT QBindingStorage @@ -82,6 +87,8 @@ public: bool isEmpty() { return !d; } + const QBindingStatus *status(QtPrivate::QBindingStatusAccessToken) const; + void registerDependency(const QUntypedPropertyData *data) const { if (!bindingStatus->currentlyEvaluatingBinding) @@ -106,6 +113,7 @@ public: return bindingData_helper(data, create); } private: + void reinitAfterThreadMove(); void clear(); void registerDependency_helper(const QUntypedPropertyData *data) const; #if QT_CORE_REMOVED_SINCE(6, 2) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 13708be391..5275fc4bf7 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -505,6 +505,13 @@ bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const return false; } +void QObjectPrivate::reinitBindingStorageAfterThreadMove() +{ + bindingStorage.reinitAfterThreadMove(); + for (int i = 0; i < children.size(); ++i) + children[i]->d_func()->reinitBindingStorageAfterThreadMove(); +} + /*! \internal */ @@ -1641,7 +1648,16 @@ void QObject::moveToThread(QThread *targetThread) currentData->ref(); // move the object - d_func()->setThreadData_helper(currentData, targetData); + auto threadPrivate = targetThread + ? static_cast<QThreadPrivate *>(QThreadPrivate::get(targetThread)) + : nullptr; + QBindingStatus *bindingStatus = threadPrivate + ? threadPrivate->bindingStatus() + : nullptr; + if (threadPrivate && !bindingStatus) { + threadPrivate->addObjectWithPendingBindingStatusChange(this); + } + d_func()->setThreadData_helper(currentData, targetData, bindingStatus); locker.unlock(); @@ -1656,14 +1672,20 @@ void QObjectPrivate::moveToThread_helper() QCoreApplication::sendEvent(q, &e); for (int i = 0; i < children.size(); ++i) { QObject *child = children.at(i); + child->d_func()->bindingStorage.clear(); child->d_func()->moveToThread_helper(); } } -void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData *targetData) +void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData *targetData, QBindingStatus *status) { Q_Q(QObject); + if (status) { + // the new thread is already running + this->bindingStorage.bindingStatus = status; + } + // move posted events int eventsMoved = 0; for (int i = 0; i < currentData->postEventList.size(); ++i) { @@ -1718,7 +1740,7 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData for (int i = 0; i < children.size(); ++i) { QObject *child = children.at(i); - child->d_func()->setThreadData_helper(currentData, targetData); + child->d_func()->setThreadData_helper(currentData, targetData, status); } } diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index ef785ddc24..67b751935e 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -111,7 +111,7 @@ public: uint willBeWidget : 1; // for handling widget-specific bits in QObject's ctor uint wasWidget : 1; // for properly cleaning up in QObject's dtor uint unused : 21; - int postedEvents; + QAtomicInt postedEvents; QDynamicMetaObjectData *metaObject; QBindingStorage bindingStorage; diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index ac77d898da..1b0706e356 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -350,7 +350,7 @@ public: void setParent_helper(QObject *); void moveToThread_helper(); - void setThreadData_helper(QThreadData *currentData, QThreadData *targetData); + void setThreadData_helper(QThreadData *currentData, QThreadData *targetData, QBindingStatus *status); void _q_reregisterTimers(void *pointer); bool isSender(const QObject *receiver, const char *signal) const; @@ -372,6 +372,8 @@ public: inline void connectNotify(const QMetaMethod &signal); inline void disconnectNotify(const QMetaMethod &signal); + void reinitBindingStorageAfterThreadMove(); + template <typename Func1, typename Func2> static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot, diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 984d207204..b2ef09db2f 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -2201,6 +2201,12 @@ QBindingStorage::~QBindingStorage() QBindingStoragePrivate(d).destroy(); } +void QBindingStorage::reinitAfterThreadMove() +{ + bindingStatus = &QT_PREPEND_NAMESPACE(bindingStatus); + Q_ASSERT(bindingStatus); +} + void QBindingStorage::clear() { QBindingStoragePrivate(d).destroy(); @@ -2237,6 +2243,11 @@ QPropertyBindingData *QBindingStorage::bindingData_helper(const QUntypedProperty return QBindingStoragePrivate(d).get(data); } +const QBindingStatus *QBindingStorage::status(QtPrivate::QBindingStatusAccessToken) const +{ + return bindingStatus; +} + QPropertyBindingData *QBindingStorage::bindingData_helper(QUntypedPropertyData *data, bool create) { return QBindingStoragePrivate(d).get(data, create); @@ -2314,6 +2325,12 @@ void printMetaTypeMismatch(QMetaType actual, QMetaType expected) } // namespace BindableWarnings end +/*! + \internal + Returns the binding statusof the current thread. + */ +QBindingStatus* getBindingStatus(QtPrivate::QBindingStatusAccessToken) { return &QT_PREPEND_NAMESPACE(bindingStatus); } + } // namespace QtPrivate end QT_END_NAMESPACE diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h index 21f9478835..a3a9072793 100644 --- a/src/corelib/kernel/qproperty_p.h +++ b/src/corelib/kernel/qproperty_p.h @@ -62,6 +62,7 @@ QT_BEGIN_NAMESPACE namespace QtPrivate { Q_CORE_EXPORT bool isAnyBindingEvaluating(); + struct QBindingStatusAccessToken {}; } // Keep all classes related to QProperty in one compilation unit. Performance of this code is crucial and |