summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@nokia.com>2009-07-24 20:52:10 (GMT)
committerThiago Macieira <thiago.macieira@nokia.com>2009-07-24 20:52:10 (GMT)
commit585d01e0c2833e16899a502d53bfd62a32573b35 (patch)
treed32102e94e5a7b8ee7219a61021cde749a693908
parent3a8c8583545b4d5eb0b1fe8d17838bea2b819703 (diff)
downloadQt-585d01e0c2833e16899a502d53bfd62a32573b35.zip
Qt-585d01e0c2833e16899a502d53bfd62a32573b35.tar.gz
Qt-585d01e0c2833e16899a502d53bfd62a32573b35.tar.bz2
Revert "Revert "Add support for creating the object alongside the Data structure in QSharedPointer""
This restores the original implementation of the creating function. The next commit will make it suitable for use.
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h47
-rw-r--r--tests/auto/qsharedpointer/tst_qsharedpointer.cpp102
2 files changed, 147 insertions, 2 deletions
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index 2d48bdb..98f225b 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -48,6 +48,7 @@
#pragma qt_sync_stop_processing
#endif
+#include <new>
#include <QtCore/qatomic.h>
#include <QtCore/qobject.h> // for qobject_cast
@@ -231,6 +232,34 @@ namespace QtSharedPointer {
};
template <class T>
+ struct ExternalRefCountWithContiguousData: public ExternalRefCountData
+ {
+#ifdef Q_DECL_ALIGN
+# ifdef Q_ALIGNOF
+# define QSP_ALIGNOF(T) Q_ALIGNOF(T)
+# else
+# define QSP_ALIGNOF(T) (sizeof(T) >= 16 ? 16 : sizeof(T) >= 8 ? 8 : sizeof(T) >= 4 ? 4 : sizeof(T) >= 2 ? 2 : 1)
+# endif
+
+ char data[sizeof(T)] Q_DECL_ALIGN(QSP_ALIGNOF(T));
+ inline T *pointer() { return reinterpret_cast<T *>(data); }
+
+# undef QSP_ALIGNOF
+#else
+ union {
+ char data[sizeof(T) + 16];
+ double dummy1;
+# ifndef Q_OS_DARWIN
+ long double dummy2;
+# endif
+ };
+ inline T *pointer() { return reinterpret_cast<T *>(data + 16 - (quintptr(data) & 0xf)); }
+#endif
+
+ inline bool destroy() { this->pointer()->~T(); return true; }
+ };
+
+ template <class T>
class ExternalRefCount: public Basic<T>
{
typedef ExternalRefCountData Data;
@@ -261,6 +290,16 @@ namespace QtSharedPointer {
d = ExternalRefCountWithCustomDeleter<T, Deleter>::create(ptr, deleter);
}
+ inline void internalCreate()
+ {
+ ExternalRefCountWithContiguousData<T> *dd = new ExternalRefCountWithContiguousData<T>;
+ T *ptr = dd->pointer();
+ new (ptr) T(); // create
+
+ Basic<T>::internalConstruct(ptr);
+ d = dd;
+ }
+
inline ExternalRefCount() : d(0) { }
inline ~ExternalRefCount() { if (d && !deref()) delete d; }
inline ExternalRefCount(const ExternalRefCount<T> &other) : Basic<T>(other), d(other.d)
@@ -388,6 +427,14 @@ public:
inline void clear() { *this = QSharedPointer<T>(); }
QWeakPointer<T> toWeakRef() const;
+
+public:
+ static QSharedPointer<T> create()
+ {
+ QSharedPointer<T> result;
+ result.internalCreate();
+ return result;
+ }
};
template <class T>
diff --git a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp
index 5cb435a..dd53e3c 100644
--- a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp
+++ b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp
@@ -65,8 +65,9 @@ private slots:
void dynamicCastVirtualBase();
void dynamicCastFailure();
#endif
- void customDeleter();
void constCorrectness();
+ void customDeleter();
+ void creating();
void validConstructs();
void invalidConstructs_data();
void invalidConstructs();
@@ -104,6 +105,8 @@ public:
{
delete this;
}
+
+ virtual int classLevel() { return 1; }
};
int Data::generationCounter = 0;
int Data::destructorCounter = 0;
@@ -332,6 +335,8 @@ public:
{
delete this;
}
+
+ virtual int classLevel() { return 2; }
};
int DerivedData::derivedDestructorCounter = 0;
@@ -339,15 +344,23 @@ class Stuffing
{
public:
char buffer[16];
+ Stuffing() { for (uint i = 0; i < sizeof buffer; ++i) buffer[i] = 16 - i; }
virtual ~Stuffing() { }
};
class DiffPtrDerivedData: public Stuffing, public Data
{
+public:
+ virtual int classLevel() { return 3; }
};
class VirtualDerived: virtual public Data
{
+public:
+ int moreData;
+
+ VirtualDerived() : moreData(0xc0ffee) { }
+ virtual int classLevel() { return 4; }
};
void tst_QSharedPointer::downCast()
@@ -993,6 +1006,82 @@ void tst_QSharedPointer::customDeleter()
QCOMPARE(derivedDataDeleter.callCount, 1);
}
+void tst_QSharedPointer::creating()
+{
+ Data::generationCounter = Data::destructorCounter = 0;
+ {
+ QSharedPointer<Data> ptr = QSharedPointer<Data>::create();
+ QVERIFY(ptr.data());
+ QCOMPARE(Data::generationCounter, 1);
+ QCOMPARE(ptr->generation, 1);
+ QCOMPARE(Data::destructorCounter, 0);
+
+ QCOMPARE(ptr->classLevel(), 1);
+
+ ptr.clear();
+ QCOMPARE(Data::destructorCounter, 1);
+ }
+
+ Data::generationCounter = Data::destructorCounter = 0;
+ {
+ QSharedPointer<Data> ptr = QSharedPointer<Data>::create();
+ QWeakPointer<Data> weakptr = ptr;
+ QtSharedPointer::ExternalRefCountData *d = ptr.d;
+
+ ptr.clear();
+ QVERIFY(ptr.isNull());
+ QCOMPARE(Data::destructorCounter, 1);
+
+ // valgrind will complain here if something happened to the pointer
+ QVERIFY(d->weakref == 1);
+ QVERIFY(d->strongref == 0);
+ }
+
+ Data::generationCounter = Data::destructorCounter = 0;
+ DerivedData::derivedDestructorCounter = 0;
+ {
+ QSharedPointer<Data> ptr = QSharedPointer<DerivedData>::create();
+ QCOMPARE(ptr->classLevel(), 2);
+ QCOMPARE(ptr.staticCast<DerivedData>()->moreData, 0);
+ ptr.clear();
+
+ QCOMPARE(Data::destructorCounter, 1);
+ QCOMPARE(DerivedData::derivedDestructorCounter, 1);
+ }
+
+ {
+ QSharedPointer<Data> ptr = QSharedPointer<DiffPtrDerivedData>::create();
+ QCOMPARE(ptr->classLevel(), 3);
+ QCOMPARE(ptr.staticCast<DiffPtrDerivedData>()->buffer[7]+0, 16-7);
+ QCOMPARE(ptr.staticCast<DiffPtrDerivedData>()->buffer[3]+0, 16-3);
+ QCOMPARE(ptr.staticCast<DiffPtrDerivedData>()->buffer[0]+0, 16);
+ }
+
+ {
+ QSharedPointer<VirtualDerived> ptr = QSharedPointer<VirtualDerived>::create();
+ QCOMPARE(ptr->classLevel(), 4);
+ QCOMPARE(ptr->moreData, 0xc0ffee);
+
+ QSharedPointer<Data> baseptr = ptr;
+ QCOMPARE(baseptr->classLevel(), 4);
+ }
+
+ {
+ QSharedPointer<QObject> ptr = QSharedPointer<QObject>::create();
+ QCOMPARE(ptr->metaObject(), &QObject::staticMetaObject);
+
+ QPointer<QObject> qptr = ptr.data();
+ ptr.clear();
+
+ QVERIFY(qptr.isNull());
+ }
+
+ {
+ QSharedPointer<QObject> ptr = QSharedPointer<OtherObject>::create();
+ QCOMPARE(ptr->metaObject(), &OtherObject::staticMetaObject);
+ }
+}
+
void tst_QSharedPointer::validConstructs()
{
{
@@ -1044,6 +1133,9 @@ void tst_QSharedPointer::invalidConstructs_data()
<< "forwardDeclaredDestructorRunCount = 0;\n"
"{ QSharedPointer<ForwardDeclared> ptr = QSharedPointer<ForwardDeclared>(forwardPointer()); }\n"
"exit(forwardDeclaredDestructorRunCount);";
+ QTest::newRow("creating-forward-declaration")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QSharedPointer<ForwardDeclared>::create();";
// upcast without cast operator:
QTest::newRow("upcast1")
@@ -1076,10 +1168,16 @@ void tst_QSharedPointer::invalidConstructs_data()
<< "QSharedPointer<const Data> baseptr = QSharedPointer<const Data>(new Data);\n"
"qSharedPointerDynamicCast<DerivedData>(baseptr);";
#endif
- QTest::newRow("const-dropping-object-cast")
+ QTest::newRow("const-dropping-object-cast1")
<< &QTest::QExternalTest::tryCompileFail
<< "QSharedPointer<const QObject> baseptr = QSharedPointer<const QObject>(new QObject);\n"
"qSharedPointerObjectCast<QCoreApplication>(baseptr);";
+#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION
+ QTest::newRow("const-dropping-object-cast2")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QSharedPointer<const QObject> baseptr = QSharedPointer<const QObject>(new QObject);\n"
+ "qobject_cast<QCoreApplication *>(baseptr);";
+#endif
// arithmethics through automatic cast operators
QTest::newRow("arithmethic1")