diff options
Diffstat (limited to 'src/corelib/kernel/qobject.cpp')
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 5e8a97cdc0..fb01df3099 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -63,6 +63,7 @@ #include <qsharedpointer.h> #include <private/qorderedmutexlocker_p.h> +#include <private/qhooks_p.h> #include <new> @@ -138,6 +139,7 @@ static inline QMutex *signalSlotLock(const QObject *o) uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)]); } +// ### Qt >= 5.6, remove qt_add/removeObject extern "C" Q_CORE_EXPORT void qt_addObject(QObject *) {} @@ -820,6 +822,8 @@ QObject::QObject(QObject *parent) } } qt_addObject(this); + if (Q_UNLIKELY(qtHookData[QHooks::AddQObject])) + reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this); } /*! @@ -851,6 +855,8 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent) } } qt_addObject(this); + if (Q_UNLIKELY(qtHookData[QHooks::AddQObject])) + reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this); } /*! @@ -1028,6 +1034,8 @@ QObject::~QObject() d->deleteChildren(); qt_removeObject(this); + if (Q_UNLIKELY(qtHookData[QHooks::RemoveQObject])) + reinterpret_cast<QHooks::RemoveQObjectCallback>(qtHookData[QHooks::RemoveQObject])(this); if (d->parent) // remove it from parent object d->setParent_helper(0); @@ -3504,7 +3512,8 @@ void QMetaObject::connectSlotsByName(QObject *o) \a signal must be in the signal index range (see QObjectPrivate::signalIndex()). */ -static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv) +static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv, + QMutexLocker &locker) { const int *argumentTypes = c->argumentTypes.load(); if (!argumentTypes && argumentTypes != &DIRECT_CONNECTION_ONLY) { @@ -3529,8 +3538,28 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect Q_CHECK_PTR(args); types[0] = 0; // return type args[0] = 0; // return value - for (int n = 1; n < nargs; ++n) - args[n] = QMetaType::create((types[n] = argumentTypes[n-1]), argv[n]); + + if (nargs > 1) { + for (int n = 1; n < nargs; ++n) + types[n] = argumentTypes[n-1]; + + locker.unlock(); + for (int n = 1; n < nargs; ++n) + args[n] = QMetaType::create(types[n], argv[n]); + locker.relock(); + + if (!c->receiver) { + locker.unlock(); + // we have been disconnected while the mutex was unlocked + for (int n = 1; n < nargs; ++n) + QMetaType::destroy(types[n], args[n]); + free(types); + free(args); + locker.relock(); + return; + } + } + QMetaCallEvent *ev = c->isSlotObject ? new QMetaCallEvent(c->slotObj, sender, signal, nargs, types, args) : new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs, types, args); @@ -3630,7 +3659,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i // put into the event queue if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread) || (c->connectionType == Qt::QueuedConnection)) { - queued_activate(sender, signal_index, c, argv ? argv : empty_argv); + queued_activate(sender, signal_index, c, argv ? argv : empty_argv, locker); continue; #ifndef QT_NO_THREAD } else if (c->connectionType == Qt::BlockingQueuedConnection) { |