diff options
author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2012-12-17 00:28:44 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-12-17 19:50:33 +0100 |
commit | cc89509f831111aadf869b1065ec1ae01f6759b8 (patch) | |
tree | 9fb2f6bea8bccd903ec6a9f1ecba2b11f0feaa9f | |
parent | c4f433d581e2d609d2eaecc4e4b999a469950eb3 (diff) |
Delete the QSlotObject when disconnect()ing
When disconnect()ing through a QMetaObject::Connection, if the
QObjectPrivate::Connection contains a slot object, deref it, so
that it will be destroyed before the next run of cleanConnectionList.
Previously, a copy of the functor passed to connect() was kept until
QObjectPrivate::cleanConnectionLists was called (by adding a new signal,
or the sender was destroyed), even after a successful call to
disconnect(). That is, we were keeping that copy allocated without
any good reason.
Change-Id: Ie6074ea797df1611cb995dec07c5b5a742360833
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 6 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 47 |
2 files changed, 45 insertions, 8 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 20c634ad78..9091b5579e 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4294,6 +4294,12 @@ bool QObject::disconnect(const QMetaObject::Connection &connection) c->next->prev = c->prev; c->receiver = 0; + // destroy the QSlotObject, if possible + if (c->isSlotObject) { + c->slotObj->destroyIfLastRef(); + c->isSlotObject = false; + } + const_cast<QMetaObject::Connection &>(connection).d_ptr = 0; c->deref(); // has been removed from the QMetaObject::Connection object diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 76a97f89f4..581644b19f 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -5594,12 +5594,8 @@ void tst_QObject::disconnectDoesNotLeakFunctor() QVERIFY(c); QCOMPARE(countedStructObjectsCount, 2); QVERIFY(QObject::disconnect(c)); - // the connection list has been marked dirty, but not cleaned yet. - QCOMPARE(countedStructObjectsCount, 2); + QCOMPARE(countedStructObjectsCount, 1); } - // disconnect() dropped the reference that c had to the functor; - // the sender has been destroyed. Therefore, the QObjectPrivate::Connection - // refcount dropped to zero and destroyed the functor. QCOMPARE(countedStructObjectsCount, 0); } QCOMPARE(countedStructObjectsCount, 0); @@ -5616,11 +5612,46 @@ void tst_QObject::disconnectDoesNotLeakFunctor() QVERIFY(c2); QCOMPARE(countedStructObjectsCount, 2); QVERIFY(QObject::disconnect(c1)); - // the connection list has been marked dirty, but not cleaned yet. - QCOMPARE(countedStructObjectsCount, 2); + // functor object has been destroyed + QCOMPARE(countedStructObjectsCount, 1); } - // c2 still holds a reference; c1 has been cleaned up + QCOMPARE(countedStructObjectsCount, 0); + } + QCOMPARE(countedStructObjectsCount, 0); + { + CountedStruct s; + QCOMPARE(countedStructObjectsCount, 1); + QTimer timer; + + QMetaObject::Connection c = connect(&timer, &QTimer::timeout, s); + QVERIFY(c); + QCOMPARE(countedStructObjectsCount, 2); + QVERIFY(QObject::disconnect(c)); + QCOMPARE(countedStructObjectsCount, 1); + } + QCOMPARE(countedStructObjectsCount, 0); + { + QTimer timer; + + QMetaObject::Connection c = connect(&timer, &QTimer::timeout, CountedStruct()); + QVERIFY(c); + QCOMPARE(countedStructObjectsCount, 1); // only one instance, in Qt internals + QVERIFY(QObject::disconnect(c)); + QCOMPARE(countedStructObjectsCount, 0); // functor being destroyed + } + QCOMPARE(countedStructObjectsCount, 0); + { +#if defined(Q_COMPILER_LAMBDA) + CountedStruct s; + QCOMPARE(countedStructObjectsCount, 1); + QTimer timer; + + QMetaObject::Connection c = connect(&timer, &QTimer::timeout, [s](){}); + QVERIFY(c); + QCOMPARE(countedStructObjectsCount, 2); + QVERIFY(QObject::disconnect(c)); QCOMPARE(countedStructObjectsCount, 1); +#endif // Q_COMPILER_LAMBDA } QCOMPARE(countedStructObjectsCount, 0); } |