diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index c5396dcc6e..6dc5764e87 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -268,163 +268,44 @@ namespace QtSharedPointer { ~ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE; Q_DISABLE_COPY(ExternalRefCountWithContiguousData) }; - - // This is the main body of QSharedPointer. It implements the - // external reference counting functionality. - template - class ExternalRefCount - { - typedef T *ExternalRefCount:: *RestrictedBool; - typedef ExternalRefCountData Data; - public: - typedef T Type; - typedef T element_type; - typedef T value_type; - typedef value_type *pointer; - typedef const value_type *const_pointer; - typedef value_type &reference; - typedef const value_type &const_reference; - typedef qptrdiff difference_type; - - inline T *data() const { return value; } - inline bool isNull() const { return !data(); } - inline operator RestrictedBool() const { return isNull() ? 0 : &ExternalRefCount::value; } - inline bool operator !() const { return isNull(); } - inline T &operator*() const { return *data(); } - inline T *operator->() const { return data(); } - - protected: - inline void deref() - { deref(d); } - static inline void deref(Data *d) - { - if (!d) return; - if (!d->strongref.deref()) { - d->destroy(); - } - if (!d->weakref.deref()) - delete d; - } - - template - inline void internalConstruct(T *ptr, Deleter deleter) - { - if (ptr) - d = ExternalRefCountWithCustomDeleter::create(ptr, deleter); - else - d = 0; - internalFinishConstruction(ptr); - } - - inline void internalCreate() - { - d = ExternalRefCountWithContiguousData::create(&value); - } - - inline void internalFinishConstruction(T *ptr) - { - value = ptr; - if (ptr) d->setQObjectShared(ptr, true); -#ifdef QT_SHAREDPOINTER_TRACK_POINTERS - if (ptr) internalSafetyCheckAdd(d, ptr); -#endif - } - - inline ExternalRefCount() : value(0), d(0) { } - inline ExternalRefCount(Qt::Initialization) { } - - template - inline ExternalRefCount(T *ptr, Deleter deleter) // throws - { internalConstruct(ptr, deleter); } - - inline ExternalRefCount(const ExternalRefCount &other) : value(other.value), d(other.d) - { if (d) ref(); } - template - inline ExternalRefCount(const ExternalRefCount &other) : value(other.value), d(other.d) - { if (d) ref(); } - inline ~ExternalRefCount() { deref(); } - - template - inline void internalCopy(const ExternalRefCount &other) - { - Data *o = other.d; - T *actual = other.value; - if (o) - other.ref(); - qSwap(d, o); - qSwap(this->value, actual); - deref(o); - } - - inline void internalSwap(ExternalRefCount &other) - { - qSwap(d, other.d); - qSwap(this->value, other.value); - } - -#if defined(Q_NO_TEMPLATE_FRIENDS) - public: -#else - template friend class ExternalRefCount; - template friend class QT_PREPEND_NAMESPACE(QWeakPointer); - template friend QSharedPointer copyAndSetPointer(X * ptr, const QSharedPointer &src); -#endif - inline void ref() const { d->weakref.ref(); d->strongref.ref(); } - - inline void internalSet(Data *o, T *actual) - { - if (o) { - // increase the strongref, but never up from zero - // or less (-1 is used by QWeakPointer on untracked QObject) - register int tmp = o->strongref.load(); - while (tmp > 0) { - // try to increment from "tmp" to "tmp + 1" - if (o->strongref.testAndSetRelaxed(tmp, tmp + 1)) - break; // succeeded - tmp = o->strongref.load(); // failed, try again - } - - if (tmp > 0) { - o->weakref.ref(); - } else { - o->checkQObjectShared(actual); - o = 0; - } - } - - qSwap(d, o); - qSwap(this->value, actual); - if (!d || d->strongref.load() == 0) - this->value = 0; - - // dereference saved data - deref(o); - } - - Type *value; - Data *d; - }; } // namespace QtSharedPointer -template -class QSharedPointer: public QtSharedPointer::ExternalRefCount +template class QSharedPointer { - typedef typename QtSharedPointer::ExternalRefCount BaseClass; + typedef T *QSharedPointer:: *RestrictedBool; + typedef QtSharedPointer::ExternalRefCountData Data; public: - inline QSharedPointer() { } - // inline ~QSharedPointer() { } + typedef T Type; + typedef T element_type; + typedef T value_type; + typedef value_type *pointer; + typedef const value_type *const_pointer; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef qptrdiff difference_type; - inline explicit QSharedPointer(T *ptr) : BaseClass(ptr, &QtSharedPointer::normalDeleter) // throws - { } + inline T *data() const { return value; } + inline bool isNull() const { return !data(); } + inline operator RestrictedBool() const { return isNull() ? 0 : &QSharedPointer::value; } + inline bool operator !() const { return isNull(); } + inline T &operator*() const { return *data(); } + inline T *operator->() const { return data(); } + + QSharedPointer() : value(0), d(0) { } + ~QSharedPointer() { deref(); } + + inline explicit QSharedPointer(T *ptr) // throws + { internalConstruct(ptr, &QtSharedPointer::normalDeleter); } template - inline QSharedPointer(T *ptr, Deleter d) : BaseClass(ptr, d) // throws - { } + inline QSharedPointer(T *ptr, Deleter deleter) : value(ptr) // throws + { internalConstruct(ptr, deleter); } - inline QSharedPointer(const QSharedPointer &other) : BaseClass(other) { } + inline QSharedPointer(const QSharedPointer &other) : value(other.value), d(other.d) + { if (d) ref(); } inline QSharedPointer &operator=(const QSharedPointer &other) { - BaseClass::internalCopy(other); + internalCopy(other); return *this; } #ifdef Q_COMPILER_RVALUE_REFS @@ -436,24 +317,24 @@ public: #endif template - inline QSharedPointer(const QSharedPointer &other) : BaseClass(other) - { } + inline QSharedPointer(const QSharedPointer &other) : value(other.value), d(other.d) + { if (d) ref(); } template inline QSharedPointer &operator=(const QSharedPointer &other) { QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid - BaseClass::internalCopy(other); + internalCopy(other); return *this; } template - inline QSharedPointer(const QWeakPointer &other) : BaseClass(Qt::Uninitialized) - { this->d = 0; *this = other; } + inline QSharedPointer(const QWeakPointer &other) : value(0), d(0) + { *this = other; } template inline QSharedPointer &operator=(const QWeakPointer &other) - { BaseClass::internalSet(other.d, other.value); return *this; } + { internalSet(other.d, other.value); return *this; } inline void swap(QSharedPointer &other) { QSharedPointer::internalSwap(other); } @@ -495,10 +376,6 @@ public: QWeakPointer toWeakRef() const; -protected: - inline explicit QSharedPointer(Qt::Initialization i) : BaseClass(i) {} - -public: static inline QSharedPointer create() { QSharedPointer result(Qt::Uninitialized); @@ -509,6 +386,105 @@ public: result.internalFinishConstruction(result.data()); return result; } + +private: + explicit QSharedPointer(Qt::Initialization) {} + + inline void deref() + { deref(d); } + static inline void deref(Data *d) + { + if (!d) return; + if (!d->strongref.deref()) { + d->destroy(); + } + if (!d->weakref.deref()) + delete d; + } + + template + inline void internalConstruct(T *ptr, Deleter deleter) + { + if (ptr) + d = QtSharedPointer::ExternalRefCountWithCustomDeleter::create(ptr, deleter); + else + d = 0; + internalFinishConstruction(ptr); + } + + inline void internalCreate() + { + d = QtSharedPointer::ExternalRefCountWithContiguousData::create(&value); + } + + inline void internalFinishConstruction(T *ptr) + { + value = ptr; + if (ptr) d->setQObjectShared(ptr, true); +#ifdef QT_SHAREDPOINTER_TRACK_POINTERS + if (ptr) internalSafetyCheckAdd(d, ptr); +#endif + } + + template + inline void internalCopy(const QSharedPointer &other) + { + Data *o = other.d; + T *actual = other.value; + if (o) + other.ref(); + qSwap(d, o); + qSwap(this->value, actual); + deref(o); + } + + inline void internalSwap(QSharedPointer &other) + { + qSwap(d, other.d); + qSwap(this->value, other.value); + } + +#if defined(Q_NO_TEMPLATE_FRIENDS) +public: +#else + template friend class QSharedPointer; + template friend class QWeakPointer; + template friend QSharedPointer QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer &src); +#endif + inline void ref() const { d->weakref.ref(); d->strongref.ref(); } + + inline void internalSet(Data *o, T *actual) + { + if (o) { + // increase the strongref, but never up from zero + // or less (-1 is used by QWeakPointer on untracked QObject) + register int tmp = o->strongref.load(); + while (tmp > 0) { + // try to increment from "tmp" to "tmp + 1" + if (o->strongref.testAndSetRelaxed(tmp, tmp + 1)) + break; // succeeded + tmp = o->strongref.load(); // failed, try again + } + + if (tmp > 0) { + o->weakref.ref(); + } else { + o->checkQObjectShared(actual); + o = 0; + } + } + + qSwap(d, o); + qSwap(this->value, actual); + if (!d || d->strongref.load() == 0) + this->value = 0; + + // dereference saved data + deref(o); + } + + Type *value; + Data *d; }; template diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp index b8cf0a7b78..70caad856b 100644 --- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp @@ -118,7 +118,7 @@ public: }; template static inline -QtSharedPointer::ExternalRefCountData *refCountData(const QtSharedPointer::ExternalRefCount &b) +QtSharedPointer::ExternalRefCountData *refCountData(const QSharedPointer &b) { // access d-pointer: struct Dummy { @@ -126,7 +126,7 @@ QtSharedPointer::ExternalRefCountData *refCountData(const QtSharedPointer::Exter QtSharedPointer::ExternalRefCountData* data; }; // sanity checks: - Q_STATIC_ASSERT(sizeof(QtSharedPointer::ExternalRefCount) == sizeof(Dummy)); + Q_STATIC_ASSERT(sizeof(QSharedPointer) == sizeof(Dummy)); Q_ASSERT(static_cast(static_cast(&b))->value == b.data()); return static_cast(static_cast(&b))->data; }