diff -r b72c6db6890b -r 5dc02b23752f src/corelib/kernel/qobject.cpp --- a/src/corelib/kernel/qobject.cpp Wed Jun 23 19:07:03 2010 +0300 +++ b/src/corelib/kernel/qobject.cpp Tue Jul 06 15:10:48 2010 +0300 @@ -101,7 +101,7 @@ /** \internal * mutex to be locked when accessing the connectionlists or the senders list */ -static QMutex *signalSlotLock(const QObject *o) +static inline QMutex *signalSlotLock(const QObject *o) { if (!signalSlotMutexes) { QMutexPool *mp = new QMutexPool; @@ -125,14 +125,17 @@ } } +void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0; +void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0; + QObjectData::~QObjectData() {} -QDeclarativeData::~QDeclarativeData() {} QObjectPrivate::QObjectPrivate(int version) : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0) { if (version != QObjectPrivateVersion) - qFatal("Cannot mix incompatible Qt libraries"); + qFatal("Cannot mix incompatible Qt library (version 0x%x) with this library (version 0x%x)", + version, QObjectPrivateVersion); // QObjectData initialization q_ptr = 0; @@ -390,27 +393,6 @@ } } -QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver, - Sender *sender) -{ - Sender *previousSender = receiver->d_func()->currentSender; - receiver->d_func()->currentSender = sender; - return previousSender; -} - -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; -} - - typedef QMultiHash GuardHash; Q_GLOBAL_STATIC(GuardHash, guardHash) Q_GLOBAL_STATIC(QMutex, guardHashLock) @@ -495,15 +477,6 @@ void QObjectPrivate::clearGuards(QObject *object) { QObjectPrivate *priv = QObjectPrivate::get(object); - QGuard *guard = priv->extraData ? priv->extraData->objectGuards : 0; - while (guard) { - QGuard *g = guard; - guard = guard->next; - g->o = 0; - g->prev = 0; - g->next = 0; - g->objectDestroyed(object); - } if (!priv->hasGuards) return; @@ -569,7 +542,7 @@ \reentrant - QObject is the heart of the \l{Qt object model}. The central + QObject is the heart of the Qt \l{Object Model}. The central feature in this model is a very powerful mechanism for seamless object communication called \l{signals and slots}. You can connect a signal to a slot with connect() and destroy the @@ -578,13 +551,13 @@ protected functions connectNotify() and disconnectNotify() make it possible to track connections. - QObjects organize themselves in \l {Object Trees and Object - Ownership} {object trees}. When you create a QObject with another - object as parent, the object will automatically add itself to the - parent's children() list. The parent takes ownership of the - object; i.e., it will automatically delete its children in its - destructor. You can look for an object by name and optionally type - using findChild() or findChildren(). + QObjects organize themselves in \l {Object Trees & Ownership} + {object trees}. When you create a QObject with another object as + parent, the object will automatically add itself to the parent's + children() list. The parent takes ownership of the object; i.e., + it will automatically delete its children in its destructor. You + can look for an object by name and optionally type using + findChild() or findChildren(). Every object has an objectName() and its class name can be found via the corresponding metaObject() (see QMetaObject::className()). @@ -636,7 +609,7 @@ Qt classes derived from QObject (direct or indirect) use this macro to declare their copy constructor and assignment operator to be private. The reasoning is found in the discussion on - \l{Identity vs Value} {Identity vs Value} on the \l{Qt Object + \l{Identity vs Value} {Identity vs Value} on the Qt \l{Object Model} page. The main consequence is that you should use pointers to QObject @@ -683,7 +656,7 @@ \l{Writing Source Code for Translation} document. \sa QMetaObject, QPointer, QObjectCleanupHandler, Q_DISABLE_COPY() - \sa {Object Trees and Object Ownership} + \sa {Object Trees & Ownership} */ /*! @@ -871,7 +844,7 @@ // all the signal/slots connections are still in place - if we don't // quit now, we will crash pretty soon. qWarning("Detected an unexpected exception in ~QObject while emitting destroyed()."); -#if defined(Q_AUTOTEST_EXPORT) && !defined(QT_NO_EXCEPTIONS) +#if defined(Q_BUILD_INTERNAL) && !defined(QT_NO_EXCEPTIONS) struct AutotestException : public std::exception { const char *what() const throw() { return "autotest swallow"; } @@ -884,26 +857,22 @@ } if (d->declarativeData) - d->declarativeData->destroyed(this); - - { - QMutex *signalSlotMutex = 0; - QT_TRY { - signalSlotMutex = signalSlotLock(this); - } QT_CATCH(const std::bad_alloc &) { - // out of memory - swallow to prevent a crash - } + QAbstractDeclarativeData::destroyed(d->declarativeData, this); + + // 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->connectionLists || d->senders) { + QMutex *signalSlotMutex = signalSlotLock(this); QMutexLocker locker(signalSlotMutex); - // set ref to zero to indicate that this object has been deleted - if (d->currentSender != 0) - d->currentSender->ref = 0; - d->currentSender = 0; - // disconnect all receivers if (d->connectionLists) { ++d->connectionLists->inUse; - for (int signal = -1; signal < d->connectionLists->count(); ++signal) { + int connectionListsCount = d->connectionLists->count(); + for (int signal = -1; signal < connectionListsCount; ++signal) { QObjectPrivate::ConnectionList &connectionList = (*d->connectionLists)[signal]; @@ -915,7 +884,7 @@ } QMutex *m = signalSlotLock(c->receiver); - bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m); + bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); if (c->receiver) { *c->prev = c->next; @@ -940,16 +909,17 @@ // disconnect all senders QObjectPrivate::Connection *node = d->senders; while (node) { - QMutex *m = signalSlotLock(node->sender); + QObject *sender = node->sender; + QMutex *m = signalSlotLock(sender); node->prev = &node; - bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m); + bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); //the node has maybe been removed while the mutex was unlocked in relock? - if (!node || signalSlotLock(node->sender) != m) { + if (!node || node->sender != sender) { m->unlock(); continue; } node->receiver = 0; - QObjectConnectionListVector *senderLists = node->sender->d_func()->connectionLists; + QObjectConnectionListVector *senderLists = sender->d_func()->connectionLists; if (senderLists) senderLists->dirty = true; @@ -976,7 +946,8 @@ qt_removeObject(this); - QCoreApplication::removePostedEvents(this); + if (d->postedEvents) + QCoreApplication::removePostedEvents(this, 0); if (d->parent) // remove it from parent object d->setParent_helper(0); @@ -1476,7 +1447,7 @@ } else if (d->threadData != currentData) { qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n" "Cannot move to target thread (%p)\n", - d->threadData->thread, currentData->thread, targetData->thread); + currentData->thread, d->threadData->thread, targetData->thread); #ifdef Q_WS_MAC qWarning("On Mac OS X, you might be loading two sets of Qt binaries into the same process. " @@ -2030,6 +2001,8 @@ } } } + if (!wasDeleted && declarativeData) + QAbstractDeclarativeData::parentChanged(declarativeData, q, o); } /*! @@ -2510,20 +2483,25 @@ const QMetaObject *smeta = sender->metaObject(); const char *signal_arg = signal; ++signal; //skip code - int signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal); + int signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false); if (signal_index < 0) { // check for normalized signatures tmp_signal_name = QMetaObject::normalizedSignature(signal - 1); signal = tmp_signal_name.constData() + 1; smeta = sender->metaObject(); - signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal); - - if (signal_index < 0) { - err_method_notfound(sender, signal_arg, "connect"); - err_info_about_objects("connect", sender, receiver); - return false; - } + signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false); + } + if (signal_index < 0) { + // re-use tmp_signal_name and signal from above + + smeta = sender->metaObject(); + signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true); + } + if (signal_index < 0) { + err_method_notfound(sender, signal_arg, "connect"); + err_info_about_objects("connect", sender, receiver); + return false; } signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index); int signalOffset, methodOffset; @@ -2543,16 +2521,21 @@ int method_index = -1; switch (membcode) { case QSLOT_CODE: - method_index = rmeta->indexOfSlot(method); + method_index = QMetaObjectPrivate::indexOfSlot(rmeta, method, false); break; case QSIGNAL_CODE: - method_index = rmeta->indexOfSignal(method); + method_index = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false); + if (method_index >= 0) + method_index += rmeta->methodOffset(); break; } if (method_index < 0) { // check for normalized methods tmp_method_name = QMetaObject::normalizedSignature(method); method = tmp_method_name.constData(); + + // rmeta may have been modified above + rmeta = receiver->metaObject(); switch (membcode) { case QSLOT_CODE: method_index = rmeta->indexOfSlot(method); @@ -2740,7 +2723,9 @@ do { int signal_index = -1; if (signal) { - signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal); + signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false); + if (signal_index < 0) + signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true); if (signal_index < 0) break; signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index); @@ -3221,9 +3206,9 @@ argv ? argv : empty_argv); } + QThreadData *currentThreadData = QThreadData::current(); + QMutexLocker locker(signalSlotLock(sender)); - QThreadData *currentThreadData = QThreadData::current(); - QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists; if (!connectionLists) { locker.unlock(); @@ -3319,7 +3304,7 @@ if (connectionLists->orphaned) { if (!connectionLists->inUse) delete connectionLists; - } else { + } else if (connectionLists->dirty) { sender->d_func()->cleanConnectionLists(); } @@ -3363,7 +3348,9 @@ { Q_Q(const QObject); const QMetaObject *base = q->metaObject(); - int relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName); + int relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, false); + if (relative_index < 0) + relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, true); if (relative_index < 0) return relative_index; relative_index = QMetaObjectPrivate::originalClone(base, relative_index);