diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2012-05-23 20:26:58 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-10-10 08:45:22 +0200 |
commit | 267b1a791d9527fed34c44c53440298331224542 (patch) | |
tree | 93e7070bde7ea65dbdedafcb6e3c1074cfe89871 /src/corelib/tools/qsharedpointer_impl.h | |
parent | 1c8739eda12b79943fd587e9e724f734938244c7 (diff) |
Optimise the deletion of a QSharedPointer with no custom deleter
When QSharedPointer is created with no user-specified custom deleter,
instead of storing a pointer in ExternalRefCount::destroyer to a
static function which, in turn, calls normalDeleter<T> indirectly (via
another function pointer), specialise the CustomDeleter class and make
it not store the pointer, but instead do the deleting directly.
The benefits are:
- the QSharedPointer's private data is smaller
- there is no double-indirection via indirect jumps to the actual
deleter
Change-Id: Ice5653c144912efb1226e432267a047b9799aaca
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Diffstat (limited to 'src/corelib/tools/qsharedpointer_impl.h')
-rw-r--r-- | src/corelib/tools/qsharedpointer_impl.h | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 4b52c5a9dc..d0422175f5 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -116,7 +116,7 @@ namespace QtSharedPointer { template <class T, typename Deleter> inline void executeDeleter(T *t, Deleter d) { d(t); } - template <class T> inline void normalDeleter(T *t) { delete t; } + struct NormalDeleter {}; // this uses partial template specialization template <class T> struct RemovePointer; @@ -165,6 +165,33 @@ namespace QtSharedPointer { }; // sizeof(ExternalRefCountData) = 12 (32-bit) / 16 (64-bit) + template <class T, typename Deleter> + struct CustomDeleter + { + Deleter deleter; + T *ptr; + + CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {} + void execute() { executeDeleter(ptr, deleter); } + }; + // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*) + padding + // for Deleter = stateless functor: 8 (32-bit) / 16 (64-bit) due to padding + // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit) + // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC) + + // This specialization of CustomDeleter for a deleter of type NormalDeleter + // is an optimization: instead of storing a pointer to a function that does + // the deleting, we simply delete the pointer ourselves. + template <class T> + struct CustomDeleter<T, NormalDeleter> + { + T *ptr; + + CustomDeleter(T *p, NormalDeleter) : ptr(p) {} + void execute() { delete ptr; } + }; + // sizeof(CustomDeleter specialization) = sizeof(void*) + // This class extends ExternalRefCountData and implements // the static function that deletes the object. The pointer and the // custom deleter are kept in the "extra" member so we can construct @@ -174,27 +201,15 @@ namespace QtSharedPointer { { typedef ExternalRefCountWithCustomDeleter Self; typedef ExternalRefCountData BaseClass; - - struct CustomDeleter - { - Deleter deleter; - T *ptr; - - inline CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {} - }; - CustomDeleter extra; - // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*) + padding - // for Deleter = stateless functor: 8 (32-bit) / 16 (64-bit) due to padding - // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit) - // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC) + CustomDeleter<T, Deleter> extra; static inline void deleter(ExternalRefCountData *self) { Self *realself = static_cast<Self *>(self); - executeDeleter(realself->extra.ptr, realself->extra.deleter); + realself->extra.execute(); // delete the deleter too - realself->extra.~CustomDeleter(); + realself->extra.~CustomDeleter<T, Deleter>(); } static void safetyCheckDeleter(ExternalRefCountData *self) { @@ -207,7 +222,7 @@ namespace QtSharedPointer { Self *d = static_cast<Self *>(::operator new(sizeof(Self))); // initialize the two sub-objects - new (&d->extra) CustomDeleter(ptr, userDeleter); + new (&d->extra) CustomDeleter<T, Deleter>(ptr, userDeleter); new (d) BaseClass(actualDeleter); // can't throw return d; @@ -292,7 +307,7 @@ public: ~QSharedPointer() { deref(); } inline explicit QSharedPointer(T *ptr) : value(ptr) // noexcept - { internalConstruct(ptr, &QtSharedPointer::normalDeleter<T>); } + { internalConstruct(ptr, QtSharedPointer::NormalDeleter()); } template <typename Deleter> inline QSharedPointer(T *ptr, Deleter deleter) : value(ptr) // throws |