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) <ogoffart@woboq.com>
This commit is contained in:
parent
a65752c71b
commit
ab92b9e400
@ -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<QMetaCallEvent*>(e);
|
||||
|
||||
QConnectionSenderSwitcher sw(this, const_cast<QObject*>(mce->sender()), mce->signalId());
|
||||
QObjectPrivate::Sender sender(this, const_cast<QObject*>(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<QtPrivate::QSlotObjectBase, QSlotObjectBaseDeleter> obj(c->slotObj);
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user