From ab92b9e40025dcf08c14232de762a268201a78b4 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 4 Jan 2019 08:55:40 +0100 Subject: [PATCH] Simplify the code required for switching the current sender Squeezes another percent of performance out of QMetaObject::activate(). Change-Id: I620b8c578681280efcc9bec50cfb1020d2afc928 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.cpp | 55 +++++++--------------------------- src/corelib/kernel/qobject_p.h | 50 ++++++++++++++----------------- 2 files changed, 33 insertions(+), 72 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 0c81e416daf..f7983f32511 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -166,39 +166,6 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *) {} #endif -struct QConnectionSenderSwitcher { - QObject *receiver; - QObjectPrivate::Sender *previousSender; - QObjectPrivate::Sender currentSender; - bool switched; - - inline QConnectionSenderSwitcher() : switched(false) {} - - inline QConnectionSenderSwitcher(QObject *receiver, QObject *sender, int signal_absolute_id) - { - switchSender(receiver, sender, signal_absolute_id); - } - - inline void switchSender(QObject *receiver, QObject *sender, int signal_absolute_id) - { - this->receiver = receiver; - currentSender.sender = sender; - currentSender.signal = signal_absolute_id; - currentSender.ref = 1; - previousSender = QObjectPrivate::setCurrentSender(receiver, ¤tSender); - switched = true; - } - - inline ~QConnectionSenderSwitcher() - { - if (switched) - QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); - } -private: - Q_DISABLE_COPY(QConnectionSenderSwitcher) -}; - - void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0; void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = 0; void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0; @@ -938,10 +905,10 @@ QObject::~QObject() } } - // set ref to zero to indicate that this object has been deleted - if (d->currentSender != 0) - d->currentSender->ref = 0; - d->currentSender = 0; + if (d->currentSender) { + d->currentSender->receiverDeleted(); + d->currentSender = nullptr; + } if (d->connectionLists || d->senders) { QMutex *signalSlotMutex = signalSlotLock(this); @@ -1272,7 +1239,7 @@ bool QObject::event(QEvent *e) { QMetaCallEvent *mce = static_cast(e); - QConnectionSenderSwitcher sw(this, const_cast(mce->sender()), mce->signalId()); + QObjectPrivate::Sender sender(this, const_cast(mce->sender()), mce->signalId()); mce->placeMetaCall(this); break; @@ -1576,9 +1543,10 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData } // the current emitting thread shouldn't restore currentSender after calling moveToThread() - if (currentSender) - currentSender->ref = 0; - currentSender = 0; + if (currentSender) { + currentSender->receiverDeleted(); + currentSender = nullptr; + } // set new thread data targetData->ref(); @@ -3755,11 +3723,8 @@ void doActivate(QObject *sender, int signal_index, void **argv) #endif } - QConnectionSenderSwitcher sw; + QObjectPrivate::Sender senderData(receiverInSameThread ? receiver : nullptr, sender, signal_index); - if (receiverInSameThread) { - sw.switchSender(receiver, sender, signal_index); - } if (c->isSlotObject) { c->slotObj->ref(); QScopedPointer obj(c->slotObj); diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index a260ed680e1..ab20064c655 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -167,9 +167,31 @@ public: struct Sender { + Sender(QObject *receiver, QObject *sender, int signal) + : receiver(receiver), sender(sender), signal(signal) + { + if (receiver) { + previous = receiver->d_func()->currentSender; + receiver->d_func()->currentSender = this; + } + } + ~Sender() + { + if (receiver) + receiver->d_func()->currentSender = previous; + } + void receiverDeleted() + { + Sender *s = this; + while (s) { + s->receiver = nullptr; + s = s->previous; + } + } + Sender *previous; + QObject *receiver; QObject *sender; int signal; - int ref; }; @@ -189,12 +211,6 @@ public: void addConnection(int signal, Connection *c); void cleanConnectionLists(); - static inline Sender *setCurrentSender(QObject *receiver, - Sender *sender); - static inline void resetCurrentSender(QObject *receiver, - Sender *currentSender, - Sender *previousSender); - static QObjectPrivate *get(QObject *o) { return o->d_func(); } @@ -251,26 +267,6 @@ inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) cons && QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index); } -inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver, - Sender *sender) -{ - Sender *previousSender = receiver->d_func()->currentSender; - receiver->d_func()->currentSender = sender; - return previousSender; -} - -inline void QObjectPrivate::resetCurrentSender(QObject *receiver, - Sender *currentSender, - Sender *previousSender) -{ - // ref is set to zero when this object is deleted during the metacall - if (currentSender->ref == 1) - receiver->d_func()->currentSender = previousSender; - // if we've recursed, we need to tell the caller about the objects deletion - if (previousSender) - previousSender->ref = currentSender->ref; -} - inline void QObjectPrivate::connectNotify(const QMetaMethod &signal) { q_ptr->connectNotify(signal);