From 25c5de7f168652ff5c3e6e49d09567d3ef4b41fd Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 24 Jul 2009 23:05:34 +0200 Subject: Adapt the contiguous-creator code to use the new custom deleter code. We use the same trick as the custom deleter: we allocate memory for an object of class ExternalRefCountWithContiguousData, but we do that only to be certain of the alignment requirements for T. We initialise the d-pointer via placement new and the T object is left for initialisation by the outermost function. The reason for that last trick is to support passing parameters in the future with the least amount of template functions necessary. I still plan on supporting arguments only with C++0x (maybe up to one without). --- src/corelib/tools/qsharedpointer_impl.h | 53 +++++++++++++++++---------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 98f225b..2c9cd95 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -232,31 +232,31 @@ namespace QtSharedPointer { }; template - struct ExternalRefCountWithContiguousData: public ExternalRefCountData + struct ExternalRefCountWithContiguousData: public ExternalRefCountWithDestroyFn { -#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 + typedef ExternalRefCountWithDestroyFn Parent; + typedef ExternalRefCountWithContiguousData Self; + T data; - char data[sizeof(T)] Q_DECL_ALIGN(QSP_ALIGNOF(T)); - inline T *pointer() { return reinterpret_cast(data); } + static void deleter(ExternalRefCountData *self) + { + ExternalRefCountWithContiguousData *that = + static_cast(self); + that->data.~T(); + } -# 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(data + 16 - (quintptr(data) & 0xf)); } -#endif + static inline ExternalRefCountData *create(T **ptr) + { + DestroyerFn destroy = &deleter; + Self *d = static_cast(::operator new(sizeof(Self))); + + // initialize the d-pointer sub-object + // leave d->data uninitialized + new (d) Parent(destroy); // can't throw - inline bool destroy() { this->pointer()->~T(); return true; } + *ptr = &d->data; + return d; + } }; template @@ -292,12 +292,10 @@ namespace QtSharedPointer { inline void internalCreate() { - ExternalRefCountWithContiguousData *dd = new ExternalRefCountWithContiguousData; - T *ptr = dd->pointer(); - new (ptr) T(); // create + T *ptr; + d = ExternalRefCountWithContiguousData::create(&ptr); Basic::internalConstruct(ptr); - d = dd; } inline ExternalRefCount() : d(0) { } @@ -429,10 +427,13 @@ public: QWeakPointer toWeakRef() const; public: - static QSharedPointer create() + static inline QSharedPointer create() { QSharedPointer result; result.internalCreate(); + + // now initialize the data + new (result.data()) T(); return result; } }; -- cgit v0.12