summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qsharedpointer_impl.h
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2012-05-23 20:26:58 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-10-10 08:45:22 +0200
commit267b1a791d9527fed34c44c53440298331224542 (patch)
tree93e7070bde7ea65dbdedafcb6e3c1074cfe89871 /src/corelib/tools/qsharedpointer_impl.h
parent1c8739eda12b79943fd587e9e724f734938244c7 (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.h51
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