diff options
author | Thiago Macieira <thiago.macieira@nokia.com> | 2009-07-31 20:10:49 (GMT) |
---|---|---|
committer | Thiago Macieira <thiago.macieira@nokia.com> | 2009-08-03 12:14:57 (GMT) |
commit | 1c5cf2e3d6f091593aec237bbb527cb8cdb964c4 (patch) | |
tree | 3e2e7979636f7a744a5101930c0f23669cdebb7e /src | |
parent | 7e0b201285c712a3c98c848033bbd8e5ab75a590 (diff) | |
download | Qt-1c5cf2e3d6f091593aec237bbb527cb8cdb964c4.zip Qt-1c5cf2e3d6f091593aec237bbb527cb8cdb964c4.tar.gz Qt-1c5cf2e3d6f091593aec237bbb527cb8cdb964c4.tar.bz2 |
Change the pointer-tracking code to work everywhere.
Currently, if you create a QSharedPointer in code with
pointer-tracking, you must ensure it gets deleted in code with
pointer-tracking, otherwise the internal safety tracker will be
"leaking" objects. The pointers would never get removed.
And if any new pointer happened to have the same pointer address
(which happens quite often), the tracker code would promptly abort the
application.
With this change, the untracking of the pointer is scheduled by the
same code that creates the tracking. This is done by "abusing" the
custom deleter code:
- for the QSharedPointer that used ExternalRefCountWithDestroyFn
already, we intercept the call to the destroy function and call the
untracking function
- for a normal QSharedPointer, we use the "normalDeleter" function as
custom deleter and chain up above
Note: the autotest only *really* works in release mode. Otherwise
functions don't get inlined and do get merged by the linker.
Reviewed-By: Bradley T. Hughes
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/tools/qsharedpointer_impl.h | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 55aeb10..b5daf5d 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -214,10 +214,19 @@ namespace QtSharedPointer { // delete the deleter too realself->extra.~Next(); } + static void safetyCheckDeleter(ExternalRefCountData *self) + { + internalSafetyCheckRemove2(self); + deleter(self); + } static inline Self *create(T *ptr, Deleter userDeleter) { +# ifdef QT_SHAREDPOINTER_TRACK_POINTERS + DestroyerFn destroy = &safetyCheckDeleter; +# else DestroyerFn destroy = &deleter; +# endif Self *d = static_cast<Self *>(::operator new(sizeof(Self))); // initialize the two sub-objects @@ -244,10 +253,19 @@ namespace QtSharedPointer { static_cast<ExternalRefCountWithContiguousData *>(self); that->data.~T(); } + static void safetyCheckDeleter(ExternalRefCountData *self) + { + internalSafetyCheckRemove2(self); + deleter(self); + } static inline ExternalRefCountData *create(T **ptr) { +# ifdef QT_SHAREDPOINTER_TRACK_POINTERS + DestroyerFn destroy = &safetyCheckDeleter; +# else DestroyerFn destroy = &deleter; +# endif ExternalRefCountWithContiguousData *d = static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData))); @@ -282,32 +300,34 @@ namespace QtSharedPointer { inline void internalConstruct(T *ptr) { - Basic<T>::internalConstruct(ptr); +#ifdef QT_SHAREDPOINTER_TRACK_POINTERS + internalConstruct<void (*)(T *)>(ptr, normalDeleter); +#else Q_ASSERT(!d); if (ptr) d = new Data; -#ifdef QT_SHAREDPOINTER_TRACK_POINTERS - if (ptr) internalSafetyCheckAdd2(d, ptr); + internalFinishConstruction(ptr); #endif } template <typename Deleter> inline void internalConstruct(T *ptr, Deleter deleter) { - Basic<T>::internalConstruct(ptr); Q_ASSERT(!d); if (ptr) d = ExternalRefCountWithCustomDeleter<T, Deleter>::create(ptr, deleter); -#ifdef QT_SHAREDPOINTER_TRACK_POINTERS - if (ptr) internalSafetyCheckAdd2(d, ptr); -#endif + internalFinishConstruction(ptr); } inline void internalCreate() { T *ptr; d = ExternalRefCountWithContiguousData<T>::create(&ptr); + Basic<T>::internalConstruct(ptr); + } + inline void internalFinishConstruction(T *ptr) + { Basic<T>::internalConstruct(ptr); #ifdef QT_SHAREDPOINTER_TRACK_POINTERS if (ptr) internalSafetyCheckAdd2(d, ptr); @@ -327,9 +347,6 @@ namespace QtSharedPointer { inline void internalDestroy() { -#ifdef QT_SHAREDPOINTER_TRACK_POINTERS - internalSafetyCheckRemove2(d); -#endif if (!d->destroy()) delete this->value; } @@ -450,6 +467,7 @@ public: // now initialize the data new (result.data()) T(); + result.internalFinishConstruction(result.data()); return result; } }; |