summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@woboq.com>2011-12-23 17:13:05 +0100
committerQt by Nokia <qt-info@nokia.com>2012-02-10 15:37:10 +0100
commit497622cafe235eadb5dd5056b196d8451ee89071 (patch)
treee7a561f55bb26c137f5d6794c393e355f957a326
parent281673e5d3e25f543590bf63bb2b97517486f4e1 (diff)
Make it possible to put QObject tracked with QWeakPointer inside QSharedPointer
Do that by keeping the QWeakPointer that track QObject independent of the ones that track QSharedPointer. QSharedPointer do not touch the sharedRefCount in QObjectPrivate anymore When converting a QWeakPointer constructed from a QObject to a QSharedPointer, it will display a warning saying one should not do that. Task-number: QTBUG-22622 Change-Id: I3595e3e7401702410776c458687ab357ad9366ab Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com> Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com> Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
-rw-r--r--src/corelib/tools/qsharedpointer.cpp28
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h8
-rw-r--r--tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp33
3 files changed, 44 insertions, 25 deletions
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index ee0aee2399..77c3d1e2cb 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -1226,24 +1226,22 @@ QT_BEGIN_NAMESPACE
/*!
\internal
This function is called for a just-created QObject \a obj, to enable
- the use of QSharedPointer and QWeakPointer.
+ the use of QSharedPointer and QWeakPointer in the future.
+ */
+void QtSharedPointer::ExternalRefCountData::setQObjectShared(const QObject *, bool)
+{}
- When QSharedPointer is active in a QObject, the object must not be deleted
- directly: the lifetime is managed by the QSharedPointer object. In that case,
- the deleteLater() and parent-child relationship in QObject only decrease
- the strong reference count, instead of deleting the object.
+/*!
+ \internal
+ This function is called when a QSharedPointer is created from a QWeakPointer
+
+ We check that the QWeakPointer was really created from a QSharedPointer, and
+ not from a QObject.
*/
-void QtSharedPointer::ExternalRefCountData::setQObjectShared(const QObject *obj, bool)
+void QtSharedPointer::ExternalRefCountData::checkQObjectShared(const QObject *)
{
- Q_ASSERT(obj);
- QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj));
-
- if (d->sharedRefcount.load() != 0)
- qFatal("QSharedPointer: pointer %p already has reference counting", obj);
- d->sharedRefcount.store(this);
-
- // QObject decreases the refcount too, so increase it up
- weakref.ref();
+ if (strongref.load() < 0)
+ qWarning("QSharedPointer: cannot create a QSharedPointer from a QObject-tracking QWeakPointer");
}
QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::getAndRef(const QObject *obj)
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index ebab027196..58010dd8d9 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -192,7 +192,9 @@ namespace QtSharedPointer {
#ifndef QT_NO_QOBJECT
Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *);
Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
+ Q_CORE_EXPORT void checkQObjectShared(const QObject *);
#endif
+ inline void checkQObjectShared(...) { }
inline void setQObjectShared(...) { }
};
// sizeof(ExternalRefCount) = 12 (32-bit) / 16 (64-bit)
@@ -432,10 +434,12 @@ namespace QtSharedPointer {
tmp = o->strongref.load(); // failed, try again
}
- if (tmp > 0)
+ if (tmp > 0) {
o->weakref.ref();
- else
+ } else {
+ o->checkQObjectShared(actual);
o = 0;
+ }
}
qSwap(d, o);
diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
index 2bae52a622..6dae58a006 100644
--- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
+++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
@@ -76,6 +76,7 @@ private slots:
void upCast();
void qobjectWeakManagement();
void noSharedPointerFromWeakQObject();
+ void sharedPointerFromQObjectWithWeak();
void weakQObjectFromSharedPointer();
void objectCast();
void differentPointers();
@@ -692,12 +693,34 @@ void tst_QSharedPointer::noSharedPointerFromWeakQObject()
QObject obj;
QWeakPointer<QObject> weak(&obj);
- QSharedPointer<QObject> strong = weak.toStrongRef();
- QVERIFY(strong.isNull());
+ {
+ QTest::ignoreMessage(QtWarningMsg , "QSharedPointer: cannot create a QSharedPointer from a QObject-tracking QWeakPointer");
+ QSharedPointer<QObject> strong = weak.toStrongRef();
+ QVERIFY(strong.isNull());
+ }
+ {
+ QTest::ignoreMessage(QtWarningMsg , "QSharedPointer: cannot create a QSharedPointer from a QObject-tracking QWeakPointer");
+ QSharedPointer<QObject> strong = weak;
+ QVERIFY(strong.isNull());
+ }
+ QCOMPARE(weak.data(), &obj);
// if something went wrong, we'll probably crash here
}
+void tst_QSharedPointer::sharedPointerFromQObjectWithWeak()
+{
+ QObject *ptr = new QObject;
+ QWeakPointer<QObject> weak = ptr;
+ {
+ QSharedPointer<QObject> shared(ptr);
+ QVERIFY(!weak.isNull());
+ QCOMPARE(shared.data(), ptr);
+ QCOMPARE(weak.data(), ptr);
+ }
+ QVERIFY(weak.isNull());
+}
+
void tst_QSharedPointer::weakQObjectFromSharedPointer()
{
// this is the inverse of the above: you're allowed to create a QWeakPointer
@@ -1767,12 +1790,6 @@ void tst_QSharedPointer::invalidConstructs_data()
<< "Data *ptr = 0;\n"
"QWeakPointer<Data> weakptr(ptr);\n";
- QTest::newRow("shared-pointer-from-unmanaged-qobject")
- << &QTest::QExternalTest::tryRunFail
- << "QObject *ptr = new QObject;\n"
- "QWeakPointer<QObject> weak = ptr;\n" // this makes the object unmanaged
- "QSharedPointer<QObject> shared(ptr);\n";
-
QTest::newRow("shared-pointer-implicit-from-uninitialized")
<< &QTest::QExternalTest::tryCompileFail
<< "Data *ptr = 0;\n"