diff options
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_wasm_p.h | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 44 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p_p.h | 13 | ||||
-rw-r--r-- | src/corelib/kernel/qproperty.cpp | 7 | ||||
-rw-r--r-- | src/corelib/kernel/qproperty_p.h | 18 |
6 files changed, 51 insertions, 37 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_wasm_p.h b/src/corelib/kernel/qeventdispatcher_wasm_p.h index 9ae92c811be..b2057af6cb7 100644 --- a/src/corelib/kernel/qeventdispatcher_wasm_p.h +++ b/src/corelib/kernel/qeventdispatcher_wasm_p.h @@ -50,7 +50,7 @@ public: void interrupt() override; void wakeUp() override; - static void runOnMainThreadAsync(std::function<void(void)> fn); + static void runOnMainThread(std::function<void(void)> fn); static void socketSelect(int timeout, int socket, bool waitForRead, bool waitForWrite, bool *selectForRead, bool *selectForWrite, bool *socketDisconnect); protected: @@ -87,7 +87,7 @@ private: static void run(std::function<void(void)> fn); static void runAsync(std::function<void(void)> fn); - static void runOnMainThread(std::function<void(void)> fn); + static void runOnMainThreadAsync(std::function<void(void)> fn); static QEventDispatcherWasm *g_mainThreadEventDispatcher; diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 9c7c70a6c88..792fe986563 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -2338,7 +2338,7 @@ QMetaMethod::MethodType QMetaMethod::methodType() const \since 5.0 Returns the meta-method that corresponds to the given \a signal, or an - invalid QMetaMethod if \a signal is not a signal of the class. + invalid QMetaMethod if \a signal is \c{nullptr} or not a signal of the class. Example: diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 65390d83fc8..a2e9b23ac6c 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -252,7 +252,7 @@ QObjectList QObjectPrivate::receiverList(const char *signal) const { QObjectList returnValue; int signal_index = signalIndex(signal); - ConnectionData *cd = connections.loadRelaxed(); + ConnectionData *cd = connections.loadAcquire(); if (signal_index < 0 || !cd) return returnValue; if (signal_index < cd->signalVectorCount()) { @@ -281,13 +281,17 @@ QObjectList QObjectPrivate::senderList() const return returnValue; } +/*! + \internal + The signalSlotLock() of the sender must be locked while calling this function +*/ inline void QObjectPrivate::ensureConnectionData() { if (connections.loadRelaxed()) return; ConnectionData *cd = new ConnectionData; cd->ref.ref(); - connections.storeRelaxed(cd); + connections.storeRelease(cd); } /*! @@ -452,7 +456,7 @@ bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) if (checkDeclarative && isDeclarativeSignalConnected(signalIndex)) return true; - ConnectionData *cd = connections.loadRelaxed(); + ConnectionData *cd = connections.loadAcquire(); if (!cd) return false; SignalVector *signalVector = cd->signalVector.loadRelaxed(); @@ -475,7 +479,7 @@ bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const { - ConnectionData *cd = connections.loadRelaxed(); + ConnectionData *cd = connections.loadAcquire(); if (!cd) return false; SignalVector *signalVector = cd->signalVector.loadRelaxed(); @@ -1015,8 +1019,8 @@ void QObjectPrivate::clearBindingStorage() outside the parent. If you still do, the destroyed() signal gives you an opportunity to detect when an object is destroyed. - \warning Deleting a QObject while pending events are waiting to - be delivered can cause a crash. You must not delete the QObject + \warning Deleting a QObject while it is handling an event + delivered to it can cause a crash. You must not delete the QObject directly if it exists in a different thread than the one currently executing. Use deleteLater() instead, which will cause the event loop to delete the object after all pending events have been @@ -1065,7 +1069,7 @@ QObject::~QObject() if (!d->isDeletingChildren && d->declarativeData && QAbstractDeclarativeData::destroyed) QAbstractDeclarativeData::destroyed(d->declarativeData, this); - QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed(); + QObjectPrivate::ConnectionData *cd = d->connections.loadAcquire(); if (cd) { if (cd->currentSender) { cd->currentSender->receiverDeleted(); @@ -1429,11 +1433,13 @@ bool QObject::event(QEvent *e) { QAbstractMetaCallEvent *mce = static_cast<QAbstractMetaCallEvent*>(e); - if (!d_func()->connections.loadRelaxed()) { + QObjectPrivate::ConnectionData *connections = d_func()->connections.loadAcquire(); + if (!connections) { QMutexLocker locker(signalSlotLock(this)); d_func()->ensureConnectionData(); + connections = d_func()->connections.loadRelaxed(); } - QObjectPrivate::Sender sender(this, const_cast<QObject*>(mce->sender()), mce->signalId()); + QObjectPrivate::Sender sender(this, const_cast<QObject*>(mce->sender()), mce->signalId(), connections); mce->placeMetaCall(this); break; @@ -1766,7 +1772,7 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData } // the current emitting thread shouldn't restore currentSender after calling moveToThread() - ConnectionData *cd = connections.loadRelaxed(); + ConnectionData *cd = connections.loadAcquire(); if (cd) { if (cd->currentSender) { cd->currentSender->receiverDeleted(); @@ -2709,8 +2715,8 @@ int QObject::receivers(const char *signal) const signal_index); } - QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed(); QMutexLocker locker(signalSlotLock(this)); + QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed(); if (cd && signal_index < cd->signalVectorCount()) { const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed(); while (c) { @@ -3968,8 +3974,8 @@ void doActivate(QObject *sender, int signal_index, void **argv) bool senderDeleted = false; { - Q_ASSERT(sp->connections.loadAcquire()); - QObjectPrivate::ConnectionDataPointer connections(sp->connections.loadRelaxed()); + Q_ASSERT(sp->connections.loadRelaxed()); + QObjectPrivate::ConnectionDataPointer connections(sp->connections.loadAcquire()); QObjectPrivate::SignalVector *signalVector = connections->signalVector.loadRelaxed(); const QObjectPrivate::ConnectionList *list; @@ -4045,7 +4051,9 @@ void doActivate(QObject *sender, int signal_index, void **argv) if (c->isSingleShot && !QObjectPrivate::removeConnection(c)) continue; - QObjectPrivate::Sender senderData(receiverInSameThread ? receiver : nullptr, sender, signal_index); + QObjectPrivate::Sender senderData( + receiverInSameThread ? receiver : nullptr, sender, signal_index, + receiverInSameThread ? QObjectPrivate::get(receiver)->connections.loadAcquire() : nullptr); if (c->isSlotObject) { SlotObjectGuard obj{c->slotObj}; @@ -4094,7 +4102,7 @@ void doActivate(QObject *sender, int signal_index, void **argv) senderDeleted = true; } if (!senderDeleted) { - sp->connections.loadRelaxed()->cleanOrphanedConnections(sender); + sp->connections.loadAcquire()->cleanOrphanedConnections(sender); if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr) signal_spy_set->signal_end_callback(sender, signal_index); @@ -5154,9 +5162,9 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s QOrderedMutexLocker locker(signalSlotLock(sender), signalSlotLock(receiver)); - if (type & Qt::UniqueConnection && slot && QObjectPrivate::get(s)->connections.loadRelaxed()) { + if (type & Qt::UniqueConnection && slot) { QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(s)->connections.loadRelaxed(); - if (connections->signalVectorCount() > signal_index) { + if (connections && connections->signalVectorCount() > signal_index) { const QObjectPrivate::Connection *c2 = connections->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed(); while (c2) { @@ -5433,7 +5441,7 @@ inline bool QObjectPrivate::removeConnection(QObjectPrivate::Connection *c) QtPrivate::QPropertyAdaptorSlotObject * QObjectPrivate::getPropertyAdaptorSlotObject(const QMetaProperty &property) { - if (auto conns = connections.loadRelaxed()) { + if (auto conns = connections.loadAcquire()) { Q_Q(QObject); const QMetaObject *metaObject = q->metaObject(); int signal_index = methodIndexToSignalIndex(&metaObject, property.notifySignalIndex()); diff --git a/src/corelib/kernel/qobject_p_p.h b/src/corelib/kernel/qobject_p_p.h index d79ce7e2b93..537ea55f4d7 100644 --- a/src/corelib/kernel/qobject_p_p.h +++ b/src/corelib/kernel/qobject_p_p.h @@ -215,19 +215,18 @@ struct QObjectPrivate::ConnectionData struct QObjectPrivate::Sender { - Sender(QObject *receiver, QObject *sender, int signal) + Sender(QObject *receiver, QObject *sender, int signal, ConnectionData *receiverConnections) : receiver(receiver), sender(sender), signal(signal) { - if (receiver) { - ConnectionData *cd = receiver->d_func()->connections.loadRelaxed(); - previous = cd->currentSender; - cd->currentSender = this; + if (receiverConnections) { + previous = receiverConnections->currentSender; + receiverConnections->currentSender = this; } } ~Sender() { if (receiver) - receiver->d_func()->connections.loadRelaxed()->currentSender = previous; + receiver->d_func()->connections.loadAcquire()->currentSender = previous; } void receiverDeleted() { @@ -237,7 +236,7 @@ struct QObjectPrivate::Sender s = s->previous; } } - Sender *previous; + Sender *previous = nullptr; QObject *receiver; QObject *sender; int signal; diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 5e78489fdae..68f6f424104 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -732,13 +732,6 @@ void QPropertyObserverPointer::setChangeHandler(QPropertyObserver::ChangeHandler ptr->next.setTag(QPropertyObserver::ObserverNotifiesChangeHandler); } -void QPropertyObserverPointer::setBindingToNotify(QPropertyBindingPrivate *binding) -{ - Q_ASSERT(ptr->next.tag() != QPropertyObserver::ObserverIsPlaceholder); - ptr->binding = binding; - ptr->next.setTag(QPropertyObserver::ObserverNotifiesBinding); -} - /*! \internal The same as as setBindingToNotify, but assumes that the tag is already correct. diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h index 77a744097eb..d8301e98852 100644 --- a/src/corelib/kernel/qproperty_p.h +++ b/src/corelib/kernel/qproperty_p.h @@ -134,7 +134,13 @@ struct QPropertyObserverPointer unlink_common(); } - void setBindingToNotify(QPropertyBindingPrivate *binding); + void setBindingToNotify(QPropertyBindingPrivate *binding) + { + Q_ASSERT(ptr->next.tag() != QPropertyObserver::ObserverIsPlaceholder); + ptr->binding = binding; + ptr->next.setTag(QPropertyObserver::ObserverNotifiesBinding); + } + void setBindingToNotify_unsafe(QPropertyBindingPrivate *binding); void setChangeHandler(QPropertyObserver::ChangeHandler changeHandler); @@ -937,7 +943,15 @@ QBindingObserverPtr::QBindingObserverPtr(QPropertyObserver *observer) noexcept : QPropertyObserverPointer{d}.binding()->addRef(); } -QBindingObserverPtr::~QBindingObserverPtr() { if (d) QPropertyObserverPointer{d}.binding()->deref(); } +QBindingObserverPtr::~QBindingObserverPtr() +{ + if (!d) + return; + + QPropertyBindingPrivate *bindingPrivate = binding(); + if (!bindingPrivate->deref()) + QPropertyBindingPrivate::destroyAndFreeMemory(bindingPrivate); +} QPropertyBindingPrivate *QBindingObserverPtr::binding() const noexcept { return QPropertyObserverPointer{d}.binding(); } |