diff options
author | Olivier Goffart <ogoffart@trolltech.com> | 2009-05-29 09:16:20 (GMT) |
---|---|---|
committer | Olivier Goffart <ogoffart@trolltech.com> | 2009-06-10 12:58:25 (GMT) |
commit | a66525c2e4c760f8ceda344cd7252431ed263654 (patch) | |
tree | 05d91ae6a8697d8fc22fcb831b0f55b38e0e420d | |
parent | 686700203aa9deeafba3bae826c7caec6d6916fd (diff) | |
download | Qt-a66525c2e4c760f8ceda344cd7252431ed263654.zip Qt-a66525c2e4c760f8ceda344cd7252431ed263654.tar.gz Qt-a66525c2e4c760f8ceda344cd7252431ed263654.tar.bz2 |
Use a linked list for the senders list inside QObject
Speed up the disconnection and object destruction
Reviewed-by: Brad
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 67 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 5 |
2 files changed, 40 insertions, 32 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 5e33a71..e953bcb 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -123,7 +123,7 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *) } QObjectPrivate::QObjectPrivate(int version) - : threadData(0), currentSender(0), currentChildBeingDeleted(0), connectionLists(0) + : threadData(0), currentSender(0), currentChildBeingDeleted(0), connectionLists(0), senders(0) { if (version != QObjectPrivateVersion) qFatal("Cannot mix incompatible Qt libraries"); @@ -287,8 +287,8 @@ QObjectList QObjectPrivate::senderList() const { QObjectList returnValue; QMutexLocker locker(signalSlotLock(q_func())); - for (int i = 0; i < senders.count(); ++i) - returnValue << senders.at(i)->sender; + for (Connection *c = senders; c; c = c->next) + returnValue << c->sender; return returnValue; } @@ -756,8 +756,10 @@ QObject::~QObject() QMutex *m = signalSlotLock(c->receiver); bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m); c = connectionList[i]; - if (c->receiver) - c->receiver->d_func()->senders.removeOne(c); + if (c->receiver) { + *c->prev = c->next; + if (c->next) c->next->prev = c->prev; + } if (needToUnlock) m->unlock(); @@ -774,29 +776,25 @@ QObject::~QObject() } // disconnect all senders - for (int i = 0; i < d->senders.count(); ) { - QObjectPrivate::Connection *s = d->senders[i]; - - QMutex *m = signalSlotLock(s->sender); + QObjectPrivate::Connection *node = d->senders; + while (node) { + QMutex *m = signalSlotLock(node->sender); + node->prev = &node; bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m); - if (m < locker.mutex()) { - if (i >= d->senders.count() || s != d->senders[i]) { - if (needToUnlock) - m->unlock(); - continue; - } + //the node has maybe been removed while the mutex was unlocked in relock? + if (!node || signalSlotLock(node->sender) != m) { + m->unlock(); + continue; } - s->receiver = 0; - QObjectConnectionListVector *senderLists = s->sender->d_func()->connectionLists; + node->receiver = 0; + QObjectConnectionListVector *senderLists = node->sender->d_func()->connectionLists; if (senderLists) senderLists->dirty = true; if (needToUnlock) m->unlock(); - ++i; + node = node->next; } - - d->senders.clear(); } if (d->pendTimer) { @@ -2281,8 +2279,8 @@ QObject *QObject::sender() const // Return 0 if d->currentSender isn't in d->senders bool found = false; - for (int i = 0; !found && i < d->senders.count(); ++i) - found = (d->senders.at(i)->sender == d->currentSender->sender); + for (QObjectPrivate::Connection *c = d->senders; c && !found; c = c->next) + found = (c->sender == d->currentSender->sender); if (!found) return 0; return d->currentSender->sender; @@ -2799,9 +2797,13 @@ bool QMetaObject::connect(const QObject *sender, int signal_index, c->method = method_index; c->connectionType = type; c->argumentTypes = types; + c->prev = &r->d_func()->senders; + c->next = *c->prev; + *c->prev = c; + if (c->next) + c->next->prev = &c->next; s->d_func()->addConnection(signal_index, c); - r->d_func()->senders.append(c); if (signal_index < 0) sender->d_func()->connectedSignals = ~0u; @@ -2851,8 +2853,10 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index, needToUnlock = QOrderedMutexLocker::relock(senderMutex, m); c = connectionList[i]; } - if (c->receiver) - c->receiver->d_func()->senders.removeOne(c); + if (c->receiver) { + *c->prev = c->next; + if (c->next) c->next->prev = c->prev; + } if (needToUnlock) m->unlock(); @@ -2878,8 +2882,10 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index, needToUnlock = QOrderedMutexLocker::relock(senderMutex, m); c = connectionList[i]; } - if (c->receiver) - c->receiver->d_func()->senders.removeOne(c); + if (c->receiver) { + *c->prev = c->next; + if (c->next) c->next->prev = c->prev; + } if (needToUnlock) m->unlock(); @@ -3417,9 +3423,8 @@ void QObject::dumpObjectInfo() // now look for connections where this object is the receiver qDebug(" SIGNALS IN"); - if (!d->senders.isEmpty()) { - for (int i = 0; i < d->senders.count(); ++i) { - const QObjectPrivate::Connection *s = d->senders.at(i); + if (d->senders) { + for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) const QMetaMethod slot = metaObject()->method(s->method); qDebug(" <-- %s::%s %s", s->sender->metaObject()->className(), @@ -3427,7 +3432,7 @@ void QObject::dumpObjectInfo() slot.signature()); } } else { - qDebug(" <None>"); + qDebug(" <None>"); } #endif } diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 96d79af..d699061 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -152,6 +152,9 @@ public: int method; uint connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking QBasicAtomicPointer<int> argumentTypes; + //senders linked list + Connection *next; + Connection **prev; ~Connection(); }; typedef QList<Connection *> ConnectionList; @@ -160,7 +163,7 @@ public: void addConnection(int signal, Connection *c); void cleanConnectionLists(); - ConnectionList senders; + Connection *senders; //linked list; static Sender *setCurrentSender(QObject *receiver, Sender *sender); |