diff options
Diffstat (limited to 'src/corelib/kernel/qobject.cpp')
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 75 |
1 files changed, 53 insertions, 22 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index c6fe787e03..14af9ac8ef 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -59,11 +59,14 @@ #include <qpair.h> #include <qvarlengtharray.h> #include <qset.h> +#if QT_CONFIG(thread) #include <qsemaphore.h> +#endif #include <qsharedpointer.h> #include <private/qorderedmutexlocker_p.h> #include <private/qhooks_p.h> +#include <qtcore_tracepoints_p.h> #include <new> @@ -418,6 +421,7 @@ void QObjectPrivate::cleanConnectionLists() { if (connectionLists->dirty && !connectionLists->inUse) { // remove broken connections + bool allConnected = false; for (int signal = -1; signal < connectionLists->count(); ++signal) { QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal]; @@ -429,11 +433,13 @@ void QObjectPrivate::cleanConnectionLists() QObjectPrivate::Connection **prev = &connectionList.first; QObjectPrivate::Connection *c = *prev; + bool connected = false; // whether the signal is still connected somewhere while (c) { if (c->receiver) { last = c; prev = &c->nextConnectionList; c = *prev; + connected = true; } else { QObjectPrivate::Connection *next = c->nextConnectionList; *prev = next; @@ -445,6 +451,14 @@ void QObjectPrivate::cleanConnectionLists() // Correct the connection list's last pointer. // As conectionList.last could equal last, this could be a noop connectionList.last = last; + + if (!allConnected && !connected && signal >= 0 + && size_t(signal) < sizeof(connectedSignals) * 8) { + // This signal is no longer connected + connectedSignals[signal >> 5] &= ~(1 << (signal & 0x1f)); + } else if (signal == -1) { + allConnected = connected; + } } connectionLists->dirty = false; } @@ -487,7 +501,7 @@ QMetaCallEvent::~QMetaCallEvent() free(types_); free(args_); } -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) if (semaphore_) semaphore_->release(); #endif @@ -523,18 +537,9 @@ void QMetaCallEvent::placeMetaCall(QObject *object) constructor and in the destructor it resets the state to what it was before the constructor ran. - \code - { - const QSignalBlocker blocker(someQObject); - // no signals here - } - \endcode + \snippet code/src_corelib_kernel_qobject.cpp 53 is thus equivalent to - \code - const bool wasBlocked = someQObject->blockSignals(true); - // no signals here - someQObject->blockSignals(wasBlocked); - \endcode + \snippet code/src_corelib_kernel_qobject.cpp 54 except the code using QSignalBlocker is safe in the face of exceptions. @@ -820,6 +825,7 @@ QObject::QObject(QObject *parent) #endif if (Q_UNLIKELY(qtHookData[QHooks::AddQObject])) reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this); + Q_TRACE(QObject_ctor, this); } /*! @@ -855,6 +861,7 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent) #endif if (Q_UNLIKELY(qtHookData[QHooks::AddQObject])) reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this); + Q_TRACE(QObject_ctor, this); } /*! @@ -1030,6 +1037,8 @@ QObject::~QObject() if (Q_UNLIKELY(qtHookData[QHooks::RemoveQObject])) reinterpret_cast<QHooks::RemoveQObjectCallback>(qtHookData[QHooks::RemoveQObject])(this); + Q_TRACE(QObject_dtor, this); + if (d->parent) // remove it from parent object d->setParent_helper(0); } @@ -2503,11 +2512,11 @@ bool QObject::isSignalConnected(const QMetaMethod &signal) const signalIndex += QMetaObjectPrivate::signalOffset(signal.mobj); - if (signalIndex < sizeof(d->connectedSignals) * 8) - return d->isSignalConnected(signalIndex); - QMutexLocker locker(signalSlotLock(this)); if (d->connectionLists) { + if (signalIndex < sizeof(d->connectedSignals) * 8 && !d->connectionLists->dirty) + return d->isSignalConnected(signalIndex); + if (signalIndex < uint(d->connectionLists->count())) { const QObjectPrivate::Connection *c = d->connectionLists->at(signalIndex).first; @@ -2518,7 +2527,7 @@ bool QObject::isSignalConnected(const QMetaMethod &signal) const } } } - return false; + return d->isDeclarativeSignalConnected(signalIndex); } /*! @@ -3645,13 +3654,17 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i if (sender->d_func()->isDeclarativeSignalConnected(signal_index) && QAbstractDeclarativeData::signalEmitted) { + Q_TRACE(QMetaObject_activate_begin_declarative_signal, sender, signal_index); QAbstractDeclarativeData::signalEmitted(sender->d_func()->declarativeData, sender, signal_index, argv); + Q_TRACE(QMetaObject_activate_end_declarative_signal, sender, signal_index); } if (!sender->d_func()->isSignalConnected(signal_index, /*checkDeclarative =*/ false) && !qt_signal_spy_callback_set.signal_begin_callback - && !qt_signal_spy_callback_set.signal_end_callback) { + && !qt_signal_spy_callback_set.signal_end_callback + && !Q_TRACE_ENABLED(QMetaObject_activate_begin_signal) + && !Q_TRACE_ENABLED(QMetaObject_activate_end_signal)) { // The possible declarative connection is done, and nothing else is connected, so: return; } @@ -3661,6 +3674,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i qt_signal_spy_callback_set.signal_begin_callback(sender, signal_index, argv ? argv : empty_argv); } + Q_TRACE(QMetaObject_activate_begin_signal, sender, signal_index); { QMutexLocker locker(signalSlotLock(sender)); @@ -3691,6 +3705,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i locker.unlock(); if (qt_signal_spy_callback_set.signal_end_callback != 0) qt_signal_spy_callback_set.signal_end_callback(sender, signal_index); + Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index); return; } @@ -3722,7 +3737,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i || (c->connectionType == Qt::QueuedConnection)) { queued_activate(sender, signal_index, c, argv ? argv : empty_argv, locker); continue; -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) } else if (c->connectionType == Qt::BlockingQueuedConnection) { if (receiverInSameThread) { qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: " @@ -3751,7 +3766,9 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i c->slotObj->ref(); QScopedPointer<QtPrivate::QSlotObjectBase, QSlotObjectBaseDeleter> obj(c->slotObj); locker.unlock(); + Q_TRACE(QMetaObject_activate_begin_slot_functor, obj.data()); obj->call(receiver, argv ? argv : empty_argv); + Q_TRACE(QMetaObject_activate_end_slot_functor, obj.data()); // Make sure the slot object gets destroyed before the mutex is locked again, as the // destructor of the slot object might also lock a mutex from the signalSlotLock() mutex pool, @@ -3767,9 +3784,11 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i locker.unlock(); if (qt_signal_spy_callback_set.slot_begin_callback != 0) qt_signal_spy_callback_set.slot_begin_callback(receiver, methodIndex, argv ? argv : empty_argv); + Q_TRACE(QMetaObject_activate_begin_slot, receiver, methodIndex); callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv ? argv : empty_argv); + Q_TRACE(QMetaObject_activate_end_slot, receiver, methodIndex); if (qt_signal_spy_callback_set.slot_end_callback != 0) qt_signal_spy_callback_set.slot_end_callback(receiver, methodIndex); locker.relock(); @@ -3782,9 +3801,11 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i method, argv ? argv : empty_argv); } + Q_TRACE(QMetaObject_activate_begin_slot, receiver, method); metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); + Q_TRACE(QMetaObject_activate_end_slot, receiver, method); if (qt_signal_spy_callback_set.slot_end_callback != 0) qt_signal_spy_callback_set.slot_end_callback(receiver, method); @@ -3805,7 +3826,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i if (qt_signal_spy_callback_set.signal_end_callback != 0) qt_signal_spy_callback_set.signal_end_callback(sender, signal_index); - + Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index); } /*! @@ -4534,6 +4555,11 @@ QDebug operator<<(QDebug dbg, const QObject *o) invoked using QMetaObject::invokeMethod(). Since \c normalMethod() function is not registered in this way, it cannot be invoked using QMetaObject::invokeMethod(). + + If an invokable member function returns a pointer to a QObject or a + subclass of QObject and it is invoked from QML, special ownership rules + apply. See \l{qtqml-cppintegration-data.html}{Data Type Conversion Between QML and C++} + for more information. */ /*! @@ -4681,7 +4707,7 @@ void qDeleteInEventHandler(QObject *o) The signal must be a function declared as a signal in the header. The slot function can be any function or functor that can be connected to the signal. - A function can be connected to a given signal if the signal as at + A function can be connected to a given signal if the signal has at least as many argument as the slot. A functor can be connected to a signal if they have exactly the same number of arguments. There must exist implicit conversion between the types of the corresponding arguments in the @@ -4721,7 +4747,7 @@ void qDeleteInEventHandler(QObject *o) The signal must be a function declared as a signal in the header. The slot function can be any function or functor that can be connected to the signal. - A function can be connected to a given signal if the signal as at + A function can be connected to a given signal if the signal has at least as many argument as the slot. A functor can be connected to a signal if they have exactly the same number of arguments. There must exist implicit conversion between the types of the corresponding arguments in the @@ -4804,7 +4830,12 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s const int *types, const QMetaObject *senderMetaObject) { if (!sender || !receiver || !slotObj || !senderMetaObject) { - qWarning("QObject::connect: invalid null parameter"); + const char *senderString = sender ? sender->metaObject()->className() + : senderMetaObject ? senderMetaObject->className() + : "Unknown"; + const char *receiverString = receiver ? receiver->metaObject()->className() + : "Unknown"; + qWarning("QObject::connect(%s, %s): invalid null parameter", senderString, receiverString); if (slotObj) slotObj->destroyIfLastRef(); return QMetaObject::Connection(); |