summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qsharedpointer_impl.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools/qsharedpointer_impl.h')
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h76
1 files changed, 56 insertions, 20 deletions
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index e381433..bce4c64 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -115,6 +115,9 @@ namespace QtSharedPointer {
template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; };
template <class T> struct RemovePointer<QWeakPointer<T> > { typedef T Type; };
+ // This class provides the basic functionality of a pointer wrapper.
+ // Its existence is mostly legacy, since originally QSharedPointer
+ // could also be used for internally-refcounted objects.
template <class T>
class Basic
{
@@ -161,6 +164,12 @@ namespace QtSharedPointer {
Type *value;
};
+ // This class is the d-pointer of QSharedPointer and QWeakPointer.
+ //
+ // It is a reference-counted reference counter. "strongref" is the inner
+ // reference counter, and it tracks the lifetime of the pointer itself.
+ // "weakref" is the outer reference counter and it tracks the lifetime of
+ // the ExternalRefCountData object.
struct ExternalRefCountData
{
QBasicAtomicInt weakref;
@@ -168,12 +177,15 @@ namespace QtSharedPointer {
inline ExternalRefCountData()
{
- QBasicAtomicInt proto = Q_BASIC_ATOMIC_INITIALIZER(1);
- weakref = strongref = proto;
+ strongref = 1;
+ weakref = 1;
}
inline ExternalRefCountData(Qt::Initialization) { }
virtual inline ~ExternalRefCountData() { Q_ASSERT(!weakref); Q_ASSERT(strongref <= 0); }
+ // overridden by derived classes
+ // returns false to indicate caller should delete the pointer
+ // returns true in case it has already done so
virtual inline bool destroy() { return false; }
#ifndef QT_NO_QOBJECT
@@ -184,18 +196,8 @@ namespace QtSharedPointer {
};
// sizeof(ExternalRefCount) = 12 (32-bit) / 16 (64-bit)
- template <class T, typename Deleter>
- struct CustomDeleter
- {
- Deleter deleter;
- T *ptr;
-
- inline CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {}
- };
- // sizeof(CustomDeleter) = sizeof(Deleter) + sizeof(void*)
- // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit)
- // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC)
-
+ // This class extends ExternalRefCountData with a pointer
+ // to a function, which is called by the destroy() function.
struct ExternalRefCountWithDestroyFn: public ExternalRefCountData
{
typedef void (*DestroyerFn)(ExternalRefCountData *);
@@ -210,13 +212,26 @@ namespace QtSharedPointer {
};
// sizeof(ExternalRefCountWithDestroyFn) = 16 (32-bit) / 24 (64-bit)
+ // This class extends ExternalRefCountWithDestroyFn and implements
+ // the static function that deletes the object. The pointer and the
+ // custom deleter are kept in the "extra" member.
template <class T, typename Deleter>
struct ExternalRefCountWithCustomDeleter: public ExternalRefCountWithDestroyFn
{
typedef ExternalRefCountWithCustomDeleter Self;
- typedef ExternalRefCountWithDestroyFn Parent;
- typedef CustomDeleter<T, Deleter> Next;
- Next extra;
+ typedef ExternalRefCountWithDestroyFn 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*)
+ // for Deleter = function pointer: 8 (32-bit) / 16 (64-bit)
+ // for Deleter = PMF: 12 (32-bit) / 24 (64-bit) (GCC)
static inline void deleter(ExternalRefCountData *self)
{
@@ -224,7 +239,7 @@ namespace QtSharedPointer {
executeDeleter(realself->extra.ptr, realself->extra.deleter);
// delete the deleter too
- realself->extra.~Next();
+ realself->extra.~CustomDeleter();
}
static void safetyCheckDeleter(ExternalRefCountData *self)
{
@@ -242,8 +257,8 @@ namespace QtSharedPointer {
Self *d = static_cast<Self *>(::operator new(sizeof(Self)));
// initialize the two sub-objects
- new (&d->extra) Next(ptr, userDeleter);
- new (d) Parent(destroy); // can't throw
+ new (&d->extra) CustomDeleter(ptr, userDeleter);
+ new (d) BaseClass(destroy); // can't throw
return d;
}
@@ -253,6 +268,10 @@ namespace QtSharedPointer {
~ExternalRefCountWithCustomDeleter();
};
+ // This class extends ExternalRefCountWithDestroyFn and adds a "T"
+ // member. That way, when the create() function is called, we allocate
+ // memory for both QSharedPointer's d-pointer and the actual object being
+ // tracked.
template <class T>
struct ExternalRefCountWithContiguousData: public ExternalRefCountWithDestroyFn
{
@@ -295,6 +314,8 @@ namespace QtSharedPointer {
~ExternalRefCountWithContiguousData();
};
+ // This is the main body of QSharedPointer. It implements the
+ // external reference counting functionality.
template <class T>
class ExternalRefCount: public Basic<T>
{
@@ -370,6 +391,12 @@ namespace QtSharedPointer {
delete this->value;
}
+ inline void internalSwap(ExternalRefCount &other)
+ {
+ qSwap(d, other.d);
+ qSwap(this->value, other.value);
+ }
+
#if defined(Q_NO_TEMPLATE_FRIENDS)
public:
#else
@@ -450,6 +477,9 @@ public:
inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
{ BaseClass::internalSet(other.d, other.value); return *this; }
+ inline void swap(QSharedPointer &other)
+ { internalSwap(other); }
+
template <class X>
QSharedPointer<X> staticCast() const
{
@@ -673,6 +703,12 @@ Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
return QWeakPointer<T>(*this);
}
+template <class T>
+inline void qSwap(QSharedPointer<T> &p1, QSharedPointer<T> &p2)
+{
+ p1.swap(p2);
+}
+
namespace QtSharedPointer {
// helper functions:
template <class X, class T>