diff options
author | Thiago Macieira <thiago.macieira@nokia.com> | 2009-08-03 16:49:16 (GMT) |
---|---|---|
committer | Thiago Macieira <thiago.macieira@nokia.com> | 2009-08-05 13:16:28 (GMT) |
commit | 021a116d48a1df3624ad2221a418f1585f7ec4f8 (patch) | |
tree | 9c4800098b95447c8f9941916be57f4d2e70663c /tests | |
parent | 435bbd4be73768f617e4a4083a345d1d8d62daa3 (diff) | |
download | Qt-021a116d48a1df3624ad2221a418f1585f7ec4f8.zip Qt-021a116d48a1df3624ad2221a418f1585f7ec4f8.tar.gz Qt-021a116d48a1df3624ad2221a418f1585f7ec4f8.tar.bz2 |
Add support for using QWeakPointer with QObject, replacing QPointer.
The problem with QPointer is that it's a simple QObject*. So the only
way for QPointer to do what it's supposed to do is if the object it's
pointing to clears all QPointers when getting deleted. That means the
QObject must know each and every QPointer pointing to it. To make
matters worse, QPointers can be deleted while the object they're
pointing to also gets deleted. So deleting QObjects must do locking.
The solution to the QPointer problem is that both QObject and the
"QPointer" reference something outside the QObject. This way,
QObject doesn't have to lock anything to destroy itself: it's simply
setting a volatile integer to zero when it gets deleted. Since the
integer is outside the QObject, the integer is also refcounted. It's also
O(1), so there's no problem having as many "QPointer".
The two-atomic-ints structure is exactly what QSharedPointer and
QWeakPointer use internally. We just abuse this structure for QObject
needs, setting the strong reference count to -1 to indicate that it's
a QObject that cannot be managed by a QSharedPointer. But QWeakPointer
can still work and replace QPointer neatly.
Reviewed-by: Bradley T. Hughes
Reviewed-by: Jarek Kobus
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/qsharedpointer/tst_qsharedpointer.cpp | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp index 210f3fa..8fd2116 100644 --- a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp @@ -67,6 +67,8 @@ private slots: void memoryManagement(); void downCast(); void upCast(); + void qobjectWeakManagement(); + void noSharedPointerFromWeakQObject(); void objectCast(); void differentPointers(); void virtualBaseDifferentPointers(); @@ -503,6 +505,109 @@ class OtherObject: public QObject Q_OBJECT }; +void tst_QSharedPointer::qobjectWeakManagement() +{ + { + QObject *obj = new QObject; + QWeakPointer<QObject> weak(obj); + QVERIFY(!weak.isNull()); + QVERIFY(weak.data() == obj); + + // now delete + delete obj; + QVERIFY(weak.isNull()); + } + check(); + + { + // same, bit with operator= + QObject *obj = new QObject; + QWeakPointer<QObject> weak; + weak = obj; + QVERIFY(!weak.isNull()); + QVERIFY(weak.data() == obj); + + // now delete + delete obj; + QVERIFY(weak.isNull()); + } + check(); + + { + // delete triggered by parent + QObject *obj, *parent; + parent = new QObject; + obj = new QObject(parent); + QWeakPointer<QObject> weak(obj); + + // now delete the parent + delete parent; + QVERIFY(weak.isNull()); + } + check(); + + { + // same as above, but set the parent after QWeakPointer is created + QObject *obj, *parent; + obj = new QObject; + QWeakPointer<QObject> weak(obj); + + parent = new QObject; + obj->setParent(parent); + + // now delete the parent + delete parent; + QVERIFY(weak.isNull()); + } + check(); + + { + // with two QWeakPointers + QObject *obj = new QObject; + QWeakPointer<QObject> weak(obj); + + { + QWeakPointer<QObject> weak2(obj); + QVERIFY(!weak2.isNull()); + QVERIFY(weak == weak2); + } + QVERIFY(!weak.isNull()); + + delete obj; + QVERIFY(weak.isNull()); + } + check(); + + { + // same, but delete the pointer while two QWeakPointers exist + QObject *obj = new QObject; + QWeakPointer<QObject> weak(obj); + + { + QWeakPointer<QObject> weak2(obj); + QVERIFY(!weak2.isNull()); + + delete obj; + QVERIFY(weak.isNull()); + QVERIFY(weak2.isNull()); + } + QVERIFY(weak.isNull()); + } + check(); +} + +void tst_QSharedPointer::noSharedPointerFromWeakQObject() +{ + // you're not allowed to create a QSharedPointer from an unmanaged QObject + QObject obj; + QWeakPointer<QObject> weak(&obj); + + QSharedPointer<QObject> strong = weak.toStrongRef(); + QVERIFY(strong.isNull()); + + // is something went wrong, we'll probably crash here +} + void tst_QSharedPointer::objectCast() { { @@ -1446,6 +1551,11 @@ void tst_QSharedPointer::invalidConstructs_data() << &QTest::QExternalTest::tryCompileFail << "QSharedPointer<Data> ptr1;\n" "QSharedPointer<int> ptr2 = qSharedPointerObjectCast<int>(ptr1);"; + + QTest::newRow("weak-pointer-from-regular-pointer") + << &QTest::QExternalTest::tryCompileFail + << "Data *ptr = 0;\n" + "QWeakPointer<Data> weakptr(ptr);\n"; } void tst_QSharedPointer::invalidConstructs() |