diff options
author | Thiago Macieira <thiago.macieira@nokia.com> | 2009-07-24 21:05:34 (GMT) |
---|---|---|
committer | Thiago Macieira <thiago.macieira@nokia.com> | 2009-07-24 21:05:34 (GMT) |
commit | 25c5de7f168652ff5c3e6e49d09567d3ef4b41fd (patch) | |
tree | 3345735961a08f5e0fa657681aa51153d11d3d01 | |
parent | 585d01e0c2833e16899a502d53bfd62a32573b35 (diff) | |
download | Qt-25c5de7f168652ff5c3e6e49d09567d3ef4b41fd.zip Qt-25c5de7f168652ff5c3e6e49d09567d3ef4b41fd.tar.gz Qt-25c5de7f168652ff5c3e6e49d09567d3ef4b41fd.tar.bz2 |
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<T>, 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).
-rw-r--r-- | src/corelib/tools/qsharedpointer_impl.h | 53 |
1 files 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 <class T> - 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<T *>(data); } + static void deleter(ExternalRefCountData *self) + { + ExternalRefCountWithContiguousData *that = + static_cast<ExternalRefCountWithContiguousData *>(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<T *>(data + 16 - (quintptr(data) & 0xf)); } -#endif + static inline ExternalRefCountData *create(T **ptr) + { + DestroyerFn destroy = &deleter; + Self *d = static_cast<Self *>(::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 <class T> @@ -292,12 +292,10 @@ namespace QtSharedPointer { inline void internalCreate() { - ExternalRefCountWithContiguousData<T> *dd = new ExternalRefCountWithContiguousData<T>; - T *ptr = dd->pointer(); - new (ptr) T(); // create + T *ptr; + d = ExternalRefCountWithContiguousData<T>::create(&ptr); Basic<T>::internalConstruct(ptr); - d = dd; } inline ExternalRefCount() : d(0) { } @@ -429,10 +427,13 @@ public: QWeakPointer<T> toWeakRef() const; public: - static QSharedPointer<T> create() + static inline QSharedPointer<T> create() { QSharedPointer<T> result; result.internalCreate(); + + // now initialize the data + new (result.data()) T(); return result; } }; |