/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the either Technology Preview License Agreement or the ** Beta Release License Agreement. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain ** additional rights. These rights are described in the Nokia Qt LGPL ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef Q_QDOC #ifndef QSHAREDPOINTER_H #error Do not include qsharedpointer_impl.h directly #endif #if 0 #pragma qt_sync_stop_processing #endif #include QT_BEGIN_HEADER QT_BEGIN_NAMESPACE QT_MODULE(Core) // Macro QSHAREDPOINTER_VERIFY_AUTO_CAST // generates a compiler error if the following construct isn't valid: // T *ptr1; // X *ptr2 = ptr1; // #ifdef QT_NO_DEBUG # define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X) qt_noop() #else template inline void qt_sharedpointer_cast_check(T *) { } # define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X) \ qt_sharedpointer_cast_check(static_cast(0)) #endif // // forward declarations // template class QWeakPointer; template class QSharedPointer; template QSharedPointer qSharedPointerCast(const QSharedPointer &ptr); template QSharedPointer qSharedPointerDynamicCast(const QSharedPointer &ptr); template QSharedPointer qSharedPointerConstCast(const QSharedPointer &ptr); namespace QtSharedPointer { template class InternalRefCount; template class ExternalRefCount; template QSharedPointer qStrongRefFromWeakHelper(const QWeakPointer &, X*); template QSharedPointer qSharedPointerCastHelper(const QSharedPointer &src, X *); template QSharedPointer qSharedPointerConstCastHelper(const QSharedPointer &src, X *); // used in debug mode to verify the reuse of pointers Q_CORE_EXPORT void internalSafetyCheckAdd(const volatile void *); Q_CORE_EXPORT void internalSafetyCheckRemove(const volatile void *); template inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)()) { (t->*memberDeleter)(); } template inline void executeDeleter(T *t, Deleter d) { d(t); } // // Depending on its template parameter, QSharedPointer derives from either // QtSharedPointer::InternalRefCount or from QtSharedPointer::ExternalRefCount. // Both of these classes derive from QtSharedPointer::Basic, which provides common // operations, // template class Basic { typedef T *Basic:: *RestrictedBool; public: typedef T Type; inline T *data() const { return value; } inline bool isNull() const { return !data(); } inline operator RestrictedBool() const { return isNull() ? 0 : &Basic::value; } inline bool operator !() const { return isNull(); } inline T &operator*() const { return *data(); } inline T *operator->() const { return data(); } protected: inline Basic() : value(0 * sizeof(T)) { } // ~Basic(); inline void verifyReconstruction(const T *ptr) { Q_ASSERT_X(!ptr || value != ptr, "QSharedPointer", "QSharedPointer violation: you cannot create two QSharedPointer objects " "from the same pointer"); // make use of the "ptr" variable in the no-op statement below // since this function is in a public header, we don't // want warnings on "unused variables" to show up everywhere ptr = 0; } inline void internalConstruct(T *ptr) { #ifdef QT_SHAREDPOINTER_TRACK_POINTERS if (ptr) internalSafetyCheckAdd(ptr); #endif value = ptr; } inline void internalDestroy() { #ifdef QT_SHAREDPOINTER_TRACK_POINTERS if (value) internalSafetyCheckRemove(value); #endif } #if defined(Q_NO_TEMPLATE_FRIENDS) public: #else template friend class QWeakPointer; #endif Type *value; }; struct ExternalRefCountData { QAtomicInt weakref; QAtomicInt strongref; inline ExternalRefCountData() : weakref(1), strongref(1) { } virtual inline ~ExternalRefCountData() { Q_ASSERT(!weakref); Q_ASSERT(!strongref); } virtual inline bool destroy() { return false; } }; template struct ExternalRefCountWithSpecializedDeleter: public ExternalRefCountData { T *ptr; Deleter deleter; inline ExternalRefCountWithSpecializedDeleter(T *p, Deleter d) : ptr(p), deleter(d) { } inline bool destroy() { executeDeleter(ptr, deleter); return true; } }; template class ExternalRefCount: public Basic { typedef ExternalRefCountData Data; typedef void (*DeleterFunction)(T *); protected: inline void ref() const { d->weakref.ref(); d->strongref.ref(); } inline bool deref() { if (!d->strongref.deref()) this->internalDestroy(); return d->weakref.deref(); } inline void internalConstruct(T *ptr) { Basic::internalConstruct(ptr); Q_ASSERT(!d); if (ptr) d = new Data; } template inline void internalConstruct(T *ptr, Deleter deleter) { Basic::internalConstruct(ptr); Q_ASSERT(!d); if (ptr) d = new ExternalRefCountWithSpecializedDeleter(ptr, deleter); } inline ExternalRefCount() : d(0) { } inline ~ExternalRefCount() { if (d && !deref()) delete d; } inline ExternalRefCount(const ExternalRefCount &other) : Basic(other), d(other.d) { if (d) ref(); } template inline void internalCopy(const ExternalRefCount &other) { internalSet(other.d, other.data()); } inline void internalDestroy() { Basic::internalDestroy(); if (!d->destroy()) delete this->value; } private: #if defined(Q_NO_TEMPLATE_FRIENDS) public: #else template friend class ExternalRefCount; template friend class QWeakPointer; template friend QSharedPointer qSharedPointerCastHelper(const QSharedPointer &src, X *); template friend QSharedPointer qSharedPointerDynamicCastHelper(const QSharedPointer &src, X *); template friend QSharedPointer qSharedPointerConstCastHelper(const QSharedPointer &src, X *); template friend QSharedPointer QtSharedPointer::qStrongRefFromWeakHelper(const QWeakPointer &src, X *); #endif inline void internalSet(Data *o, T *actual) { if (d == o) return; if (o && !o->strongref) o = 0; if (o) { verifyReconstruction(actual); o->weakref.ref(); o->strongref.ref(); } if (d && !deref()) delete d; d = o; this->value = d && d->strongref ? actual : 0; } #if defined(QT_BUILD_INTERNAL) public: #endif Data *d; private: template ExternalRefCount(const InternalRefCount &); }; } // namespace QtSharedPointer template class QSharedPointer: public QtSharedPointer::ExternalRefCount { typedef typename QtSharedPointer::ExternalRefCount BaseClass; public: inline QSharedPointer() { } // inline ~QSharedPointer() { } inline explicit QSharedPointer(T *ptr) { internalConstruct(ptr); } template inline QSharedPointer(T *ptr, Deleter d) { internalConstruct(ptr, d); } inline QSharedPointer(const QSharedPointer &other) : BaseClass(other) { } inline QSharedPointer &operator=(const QSharedPointer &other) { internalCopy(other); return *this; } inline QSharedPointer(const QWeakPointer &other) { *this = QtSharedPointer::qStrongRefFromWeakHelper(other, static_cast(0)); } inline QSharedPointer &operator=(const QWeakPointer &other) { *this = QtSharedPointer::qStrongRefFromWeakHelper(other, static_cast(0)); return *this; } template inline QSharedPointer(const QSharedPointer &other) { *this = other; } 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 internalCopy(other); return *this; } template inline QSharedPointer(const QWeakPointer &other) { *this = QtSharedPointer::qStrongRefFromWeakHelper(other, static_cast(0)); } template inline QSharedPointer &operator=(const QWeakPointer &other) { *this = qStrongRefFromWeakHelper(other, static_cast(0)); return *this; } template QSharedPointer staticCast() const { return qSharedPointerCast(*this); } template QSharedPointer dynamicCast() const { return qSharedPointerDynamicCast(*this); } template QSharedPointer constCast() const { return qSharedPointerConstCast(*this); } inline void clear() { *this = QSharedPointer(); } QWeakPointer toWeakRef() const; }; template class QWeakPointer { typedef T *QWeakPointer:: *RestrictedBool; typedef QtSharedPointer::ExternalRefCountData Data; public: inline bool isNull() const { return d == 0 || d->strongref == 0 || value == 0; } inline operator RestrictedBool() const { return isNull() ? 0 : &QWeakPointer::value; } inline bool operator !() const { return isNull(); } inline QWeakPointer() : d(0), value(0) { } inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; } inline QWeakPointer(const QWeakPointer &o) : d(o.d), value(o.value) { if (d) d->weakref.ref(); } inline QWeakPointer &operator=(const QWeakPointer &o) { internalSet(o.d, o.value); return *this; } inline QWeakPointer(const QSharedPointer &o) : d(o.d), value(o.data()) { if (d) d->weakref.ref();} inline QWeakPointer &operator=(const QSharedPointer &o) { internalSet(o.d, o.value); return *this; } template inline QWeakPointer(const QWeakPointer &o) : d(0), value(0) { *this = o; } template inline QWeakPointer &operator=(const QWeakPointer &o) { // conversion between X and T could require access to the virtual table // so force the operation to go through QSharedPointer *this = o.toStrongRef(); return *this; } template inline bool operator==(const QWeakPointer &o) const { return d == o.d && value == static_cast(o.value); } template inline bool operator!=(const QWeakPointer &o) const { return !(*this == o); } template inline QWeakPointer(const QSharedPointer &o) : d(0), value(0) { *this = o; } template inline QWeakPointer &operator=(const QSharedPointer &o) { QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid internalSet(o.d, o.data()); return *this; } template inline bool operator==(const QSharedPointer &o) const { return d == o.d && value == static_cast(o.data()); } template inline bool operator!=(const QSharedPointer &o) const { return !(*this == o); } inline void clear() { *this = QWeakPointer(); } inline QSharedPointer toStrongRef() const { return QSharedPointer(*this); } private: #if defined(Q_NO_TEMPLATE_FRIENDS) public: #else template friend QSharedPointer QtSharedPointer::qStrongRefFromWeakHelper(const QWeakPointer &src, X *); #endif inline void internalSet(Data *o, T *actual) { if (d == o) return; if (o) o->weakref.ref(); if (d && !d->weakref.deref()) delete d; d = o; value = actual; } Data *d; T *value; }; template bool operator==(const QSharedPointer &ptr1, const QSharedPointer &ptr2) { return ptr1.data() == ptr2.data(); } template bool operator!=(const QSharedPointer &ptr1, const QSharedPointer &ptr2) { return ptr1.data() != ptr2.data(); } template bool operator==(const QSharedPointer &ptr1, const X *ptr2) { return ptr1.data() == ptr2; } template bool operator==(const T *ptr1, const QSharedPointer &ptr2) { return ptr1 == ptr2.data(); } template bool operator!=(const QSharedPointer &ptr1, const X *ptr2) { return !(ptr1 == ptr2); } template bool operator!=(const T *ptr1, const QSharedPointer &ptr2) { return !(ptr2 == ptr1); } template bool operator==(const QSharedPointer &ptr1, const QWeakPointer &ptr2) { return ptr2 == ptr1; } template bool operator!=(const QSharedPointer &ptr1, const QWeakPointer &ptr2) { return ptr2 != ptr1; } template Q_INLINE_TEMPLATE QWeakPointer QSharedPointer::toWeakRef() const { return QWeakPointer(*this); } namespace QtSharedPointer { // helper functions: template Q_INLINE_TEMPLATE X *qVerifyStaticCast(T *src, X *) { return static_cast(src); // if you get an error in this line, the cast is invalid } template Q_INLINE_TEMPLATE X *qVerifyDynamicCast(T *src, X *) { return dynamic_cast(src); // if you get an error in this line, the cast is invalid } template Q_INLINE_TEMPLATE X *qVerifyConstCast(T *src, X *) { return const_cast(src); // if you get an error in this line, the cast is invalid } template Q_INLINE_TEMPLATE QSharedPointer qSharedPointerCastHelper(const QSharedPointer &src, X *) { QSharedPointer result; register T *ptr = src.data(); result.internalSet(src.d, static_cast(ptr)); return result; } template Q_INLINE_TEMPLATE QSharedPointer qSharedPointerDynamicCastHelper(const QSharedPointer &src, X *) { QSharedPointer result; register T *ptr = src.data(); result.internalSet(src.d, dynamic_cast(ptr)); return result; } template Q_INLINE_TEMPLATE QSharedPointer qSharedPointerConstCastHelper(const QSharedPointer &src, X *) { QSharedPointer result; register T *ptr = src.data(); result.internalSet(src.d, const_cast(ptr)); return result; } template Q_INLINE_TEMPLATE QSharedPointer qStrongRefFromWeakHelper (const QT_PREPEND_NAMESPACE(QWeakPointer) &src, X *) { QSharedPointer result; result.internalSet(src.d, src.value); return result; } } // cast operators template Q_INLINE_TEMPLATE QSharedPointer qSharedPointerCast(const QSharedPointer &src) { X *x = 0; QtSharedPointer::qVerifyStaticCast(src.data(), x); return QtSharedPointer::qSharedPointerCastHelper(src, x); } template Q_INLINE_TEMPLATE QSharedPointer qSharedPointerCast(const QWeakPointer &src) { return qSharedPointerCast(src.toStrongRef()); } template Q_INLINE_TEMPLATE QSharedPointer qSharedPointerDynamicCast(const QSharedPointer &src) { X *x = 0; return QtSharedPointer::qSharedPointerDynamicCastHelper(src, x); } template Q_INLINE_TEMPLATE QSharedPointer qSharedPointerDynamicCast(const QWeakPointer &src) { return qSharedPointerDynamicCast(src.toStrongRef()); } template Q_INLINE_TEMPLATE QSharedPointer qSharedPointerConstCast(const QSharedPointer &src) { X *x = 0; return QtSharedPointer::qSharedPointerConstCastHelper(src, x); } template Q_INLINE_TEMPLATE QSharedPointer qSharedPointerConstCast(const QWeakPointer &src) { X *x = 0; return QtSharedPointer::qSharedPointerConstCastHelper(src, x); } template Q_INLINE_TEMPLATE QWeakPointer qWeakPointerCast(const QSharedPointer &src) { return qSharedPointerCast(src).toWeakRef(); } QT_END_NAMESPACE QT_END_HEADER #endif