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
|
#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)(QAbstractDeclarativeData *, QObject *) = 0;
|
||||||
void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = 0;
|
void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = 0;
|
||||||
void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, 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) {
|
||||||
if (d->currentSender != 0)
|
d->currentSender->receiverDeleted();
|
||||||
d->currentSender->ref = 0;
|
d->currentSender = nullptr;
|
||||||
d->currentSender = 0;
|
}
|
||||||
|
|
||||||
if (d->connectionLists || d->senders) {
|
if (d->connectionLists || d->senders) {
|
||||||
QMutex *signalSlotMutex = signalSlotLock(this);
|
QMutex *signalSlotMutex = signalSlotLock(this);
|
||||||
@ -1272,7 +1239,7 @@ bool QObject::event(QEvent *e)
|
|||||||
{
|
{
|
||||||
QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(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);
|
mce->placeMetaCall(this);
|
||||||
break;
|
break;
|
||||||
@ -1576,9 +1543,10 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData
|
|||||||
}
|
}
|
||||||
|
|
||||||
// the current emitting thread shouldn't restore currentSender after calling moveToThread()
|
// the current emitting thread shouldn't restore currentSender after calling moveToThread()
|
||||||
if (currentSender)
|
if (currentSender) {
|
||||||
currentSender->ref = 0;
|
currentSender->receiverDeleted();
|
||||||
currentSender = 0;
|
currentSender = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// set new thread data
|
// set new thread data
|
||||||
targetData->ref();
|
targetData->ref();
|
||||||
@ -3755,11 +3723,8 @@ void doActivate(QObject *sender, int signal_index, void **argv)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QConnectionSenderSwitcher sw;
|
QObjectPrivate::Sender senderData(receiverInSameThread ? receiver : nullptr, sender, signal_index);
|
||||||
|
|
||||||
if (receiverInSameThread) {
|
|
||||||
sw.switchSender(receiver, sender, signal_index);
|
|
||||||
}
|
|
||||||
if (c->isSlotObject) {
|
if (c->isSlotObject) {
|
||||||
c->slotObj->ref();
|
c->slotObj->ref();
|
||||||
QScopedPointer<QtPrivate::QSlotObjectBase, QSlotObjectBaseDeleter> obj(c->slotObj);
|
QScopedPointer<QtPrivate::QSlotObjectBase, QSlotObjectBaseDeleter> obj(c->slotObj);
|
||||||
|
@ -167,9 +167,31 @@ public:
|
|||||||
|
|
||||||
struct Sender
|
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;
|
QObject *sender;
|
||||||
int signal;
|
int signal;
|
||||||
int ref;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -189,12 +211,6 @@ public:
|
|||||||
void addConnection(int signal, Connection *c);
|
void addConnection(int signal, Connection *c);
|
||||||
void cleanConnectionLists();
|
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) {
|
static QObjectPrivate *get(QObject *o) {
|
||||||
return o->d_func();
|
return o->d_func();
|
||||||
}
|
}
|
||||||
@ -251,26 +267,6 @@ inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) cons
|
|||||||
&& QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index);
|
&& 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)
|
inline void QObjectPrivate::connectNotify(const QMetaMethod &signal)
|
||||||
{
|
{
|
||||||
q_ptr->connectNotify(signal);
|
q_ptr->connectNotify(signal);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user