/*!
\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)
#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)
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);
void upCast();
void qobjectWeakManagement();
void noSharedPointerFromWeakQObject();
+ void sharedPointerFromQObjectWithWeak();
void weakQObjectFromSharedPointer();
void objectCast();
void differentPointers();
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
<< "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"