diff options
author | Olivier Goffart <ogoffart@trolltech.com> | 2009-11-25 20:38:39 (GMT) |
---|---|---|
committer | Olivier Goffart <ogoffart@trolltech.com> | 2009-11-26 09:28:54 (GMT) |
commit | 0f06d08a3c5eb4d0397406ed559cfaba6e137492 (patch) | |
tree | 839a9181f83e7e8fdb407e5cc97ecec2439a4bb8 | |
parent | 88c9a52646ef1c695ef0a7461ed1f6a7ce923375 (diff) | |
download | Qt-0f06d08a3c5eb4d0397406ed559cfaba6e137492.zip Qt-0f06d08a3c5eb4d0397406ed559cfaba6e137492.tar.gz Qt-0f06d08a3c5eb4d0397406ed559cfaba6e137492.tar.bz2 |
Optimize QObjectPrivate::isSignalConnected
It can be seen in the GraphicsView benchmark.
This function has to be as fast as possible.
Make the function inline.
We do not need 64bit for the connectedSignals bit array because
it is very unlikely that an object will have more than 32 signals.
(In Qt 4.5 it could have hapenned as the slot were counting in
the index)
Reviewed-by: bnilsen
Reviewed-by: Brad
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 47 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 21 | ||||
-rw-r--r-- | tests/auto/qobject/tst_qobject.cpp | 109 |
3 files changed, 135 insertions, 42 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 95602d9..4321c59 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -145,8 +145,7 @@ QObjectPrivate::QObjectPrivate(int version) receiveChildEvents = true; postedEvents = 0; extraData = 0; - for (uint i = 0; i < (sizeof connectedSignals / sizeof connectedSignals[0]); ++i) - connectedSignals[i] = 0; + connectedSignals = 0; inEventHandler = false; inThreadChangeEvent = false; deleteWatch = 0; @@ -2937,13 +2936,9 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index, QObjectPrivate *const sender_d = QObjectPrivate::get(s); if (signal_index < 0) { - for (uint i = 0; i < (sizeof sender_d->connectedSignals - / sizeof sender_d->connectedSignals[0] ); ++i) - sender_d->connectedSignals[i] = ~0u; - } else if (signal_index < (int)sizeof sender_d->connectedSignals * 8) { - uint n = (signal_index / (8 * sizeof sender_d->connectedSignals[0])); - sender_d->connectedSignals[n] |= (1 << (signal_index - n * 8 - * sizeof sender_d->connectedSignals[0])); + sender_d->connectedSignals = ~ulong(0); + } else if (signal_index < (int)sizeof(sender_d->connectedSignals) * 8) { + sender_d->connectedSignals |= ulong(1) << signal_index; } return true; @@ -3201,15 +3196,9 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign computeOffsets(m, &signalOffset, &methodOffset); int signal_index = signalOffset + local_signal_index; - if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 - && !qt_signal_spy_callback_set.signal_begin_callback - && !qt_signal_spy_callback_set.signal_end_callback) { - uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); - uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); - if ((sender->d_func()->connectedSignals[n] & m) == 0) - // nothing connected to these signals, and no spy - return; - } + + if (!sender->d_func()->isSignalConnected(signal_index)) + return; // nothing connected to these signals, and no spy if (sender->d_func()->blockSig) return; @@ -3370,28 +3359,6 @@ int QObjectPrivate::signalIndex(const char *signalName) const return relative_index + signalOffset; } -/*! \internal - - Returns true if the signal with index \a signal_index from object \a sender is connected. - Signals with indices above a certain range are always considered connected (see connectedSignals - in QObjectPrivate). If a signal spy is installed, all signals are considered connected. - - \a signal_index must be the index returned by QObjectPrivate::signalIndex; -*/ -bool QObjectPrivate::isSignalConnected(int signal_index) const -{ - if (signal_index < (int)sizeof(connectedSignals) * 8 - && !qt_signal_spy_callback_set.signal_begin_callback - && !qt_signal_spy_callback_set.signal_end_callback) { - uint n = (signal_index / (8 * sizeof connectedSignals[0])); - uint m = 1 << (signal_index - n * 8 * sizeof connectedSignals[0]); - if ((connectedSignals[n] & m) == 0) - // nothing connected to these signals, and no spy - return false; - } - return true; -} - /***************************************************************************** Properties *****************************************************************************/ diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index f087407..f899c78 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -172,7 +172,7 @@ public: } int signalIndex(const char *signalName) const; - bool isSignalConnected(int signalIdx) const; + inline bool isSignalConnected(int signalIdx) const; public: QString objectName; @@ -183,7 +183,7 @@ public: Connection *senders; // linked list of connections connected to this object Sender *currentSender; // object currently activating the object - mutable quint32 connectedSignals[2]; // 64-bit, so doesn't cause padding on 64-bit platforms + mutable ulong connectedSignals; #ifdef QT3_SUPPORT QList<QObject *> pendingChildInsertedEvents; @@ -205,6 +205,23 @@ public: int *deleteWatch; }; +/*! \internal + + Returns true if the signal with index \a signal_index from object \a sender is connected. + Signals with indices above a certain range are always considered connected (see connectedSignals + in QObjectPrivate). If a signal spy is installed, all signals are considered connected. + + \a signal_index must be the index returned by QObjectPrivate::signalIndex; +*/ +inline bool QObjectPrivate::isSignalConnected(int signal_index) const +{ + return signal_index >= (int)sizeof(connectedSignals) * 8 + || qt_signal_spy_callback_set.signal_begin_callback + || qt_signal_spy_callback_set.signal_end_callback + || (connectedSignals & (ulong(1) << signal_index)); +} + + inline void q_guard_addGuard(QGuard<QObject> *g) { QObjectPrivate *p = QObjectPrivate::get(g->o); diff --git a/tests/auto/qobject/tst_qobject.cpp b/tests/auto/qobject/tst_qobject.cpp index 5035139..67a9c46 100644 --- a/tests/auto/qobject/tst_qobject.cpp +++ b/tests/auto/qobject/tst_qobject.cpp @@ -60,6 +60,10 @@ #include <QProcess> #include "qobject.h" +#ifdef QT_BUILD_INTERNAL +#include <private/qobject_p.h> +#endif + #include <math.h> @@ -121,6 +125,7 @@ private slots: void interfaceIid(); void deleteQObjectWhenDeletingEvent(); void overloads(); + void isSignalConnected(); protected: }; @@ -3016,5 +3021,109 @@ void tst_QObject::overloads() QCOMPARE(obj2.o4_obj, qApp); //default arg of the slot } +class ManySignals : public QObject +{ Q_OBJECT + friend class tst_QObject; +signals: + void sig00(); void sig01(); void sig02(); void sig03(); void sig04(); + void sig05(); void sig06(); void sig07(); void sig08(); void sig09(); + void sig10(); void sig11(); void sig12(); void sig13(); void sig14(); + void sig15(); void sig16(); void sig17(); void sig18(); void sig19(); + void sig20(); void sig21(); void sig22(); void sig23(); void sig24(); + void sig25(); void sig26(); void sig27(); void sig28(); void sig29(); + void sig30(); void sig31(); void sig32(); void sig33(); void sig34(); + void sig35(); void sig36(); void sig37(); void sig38(); void sig39(); + void sig40(); void sig41(); void sig42(); void sig43(); void sig44(); + void sig45(); void sig46(); void sig47(); void sig48(); void sig49(); + void sig50(); void sig51(); void sig52(); void sig53(); void sig54(); + void sig55(); void sig56(); void sig57(); void sig58(); void sig59(); + void sig60(); void sig61(); void sig62(); void sig63(); void sig64(); + void sig65(); void sig66(); void sig67(); void sig68(); void sig69(); + +public slots: + void received() { rec++; } +public: + int rec; +}; + + +void tst_QObject::isSignalConnected() +{ + ManySignals o; + o.rec = 0; +#ifdef QT_BUILD_INTERNAL + QObjectPrivate *priv = QObjectPrivate::get(&o); + QVERIFY(!priv->isSignalConnected(priv->signalIndex("destroyed()"))); + QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig00()"))); + QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig05()"))); + QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig15()"))); + QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig29()"))); + if (sizeof(void *) >= 8) { //on 32bit isSignalConnected only works with the first 32 signals + QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig60()"))); + QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig61()"))); + } +#endif + + QObject::connect(&o, SIGNAL(sig00()), &o, SIGNAL(sig69())); + QObject::connect(&o, SIGNAL(sig34()), &o, SIGNAL(sig03())); + QObject::connect(&o, SIGNAL(sig69()), &o, SIGNAL(sig34())); + QObject::connect(&o, SIGNAL(sig03()), &o, SIGNAL(sig18())); + +#ifdef QT_BUILD_INTERNAL + QVERIFY(!priv->isSignalConnected(priv->signalIndex("destroyed()"))); + QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig05()"))); + QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig15()"))); + QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig29()"))); + + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig00()"))); + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig03()"))); + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig34()"))); + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()"))); + QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig18()"))); +#endif + + QObject::connect(&o, SIGNAL(sig18()), &o, SIGNAL(sig29())); + QObject::connect(&o, SIGNAL(sig29()), &o, SIGNAL(sig62())); + QObject::connect(&o, SIGNAL(sig62()), &o, SIGNAL(sig28())); + QObject::connect(&o, SIGNAL(sig28()), &o, SIGNAL(sig27())); + +#ifdef QT_BUILD_INTERNAL + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig18()"))); + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig62()"))); + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig28()"))); + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()"))); + QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig27()"))); +#endif + + QCOMPARE(o.rec, 0); + emit o.sig01(); + emit o.sig34(); + QCOMPARE(o.rec, 0); + + QObject::connect(&o, SIGNAL(sig27()), &o, SLOT(received())); + +#ifdef QT_BUILD_INTERNAL + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig00()"))); + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig03()"))); + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig34()"))); + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig18()"))); + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig62()"))); + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig28()"))); + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()"))); + QVERIFY(priv->isSignalConnected(priv->signalIndex("sig27()"))); + + QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig04()"))); + QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig21()"))); + QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig25()"))); +#endif + + emit o.sig00(); + QCOMPARE(o.rec, 1); + emit o.sig69(); + QCOMPARE(o.rec, 2); + emit o.sig36(); + QCOMPARE(o.rec, 2); +} + QTEST_MAIN(tst_QObject) #include "tst_qobject.moc" |