diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 8 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 2 | ||||
-rw-r--r-- | src/corelib/tools/qsharedpointer.cpp | 27 | ||||
-rw-r--r-- | src/corelib/tools/qsharedpointer_impl.h | 28 |
4 files changed, 60 insertions, 5 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 7e7dcaf..3417232 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -56,6 +56,7 @@ #include <qvarlengtharray.h> #include <qset.h> #include <qsemaphore.h> +#include <qsharedpointer.h> #include <private/qorderedmutexlocker_p.h> #include <private/qmutexpool_p.h> @@ -768,6 +769,13 @@ QObject::~QObject() QObjectPrivate::clearGuards(this); } + if (d->sharedRefcount) { + // indicate to all QWeakPointers that this QObject has now been deleted + d->sharedRefcount->strongref = 0; + if (!d->sharedRefcount->weakref.deref()) + delete d->sharedRefcount; + } + emit destroyed(this); if (d->declarativeData) d->declarativeData->destroyed(this); diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index e58ee6c..056dee3 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -67,6 +67,7 @@ QT_BEGIN_NAMESPACE class QVariant; class QThreadData; class QObjectConnectionListVector; +namespace QtSharedPointer { class ExternalRefCountData; } /* mirrored in QtTestLib, DON'T CHANGE without prior warning */ struct QSignalSpyCallbackSet @@ -187,6 +188,7 @@ public: // plus QPointer, which keeps a separate list QDeclarativeData *declarativeData; QGuard<QObject> *objectGuards; + QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount; int *deleteWatch; }; diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index ef4dfac..e2c5e95 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -864,6 +864,33 @@ #include <qset.h> #include <qmutex.h> +#if !defined(QT_NO_QOBJECT) +#include "../kernel/qobject_p.h" + +QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::getAndRef(const QObject *obj) +{ + Q_ASSERT(obj); + QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj)); + ExternalRefCountData *that = d->sharedRefcount; + if (that) { + that->weakref.ref(); + return that; + } + + // we can create the refcount data because it doesn't exist + ExternalRefCountData *x = new ExternalRefCountData(Qt::Uninitialized); + x->strongref = -1; + x->weakref = 2; // the QWeakPointer that called us plus the QObject itself + if (!d->sharedRefcount.testAndSetRelease(0, x)) { + delete x; + d->sharedRefcount->weakref.ref(); + } + return d->sharedRefcount; +} +#endif + + + #if !defined(QT_NO_MEMBER_TEMPLATES) //# define QT_SHARED_POINTER_BACKTRACE_SUPPORT diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 3ee407c..1fed024 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -162,13 +162,22 @@ namespace QtSharedPointer { struct ExternalRefCountData { - QAtomicInt weakref; - QAtomicInt strongref; + QBasicAtomicInt weakref; + QBasicAtomicInt strongref; - inline ExternalRefCountData() : weakref(1), strongref(1) { } - virtual inline ~ExternalRefCountData() { Q_ASSERT(!weakref); Q_ASSERT(!strongref); } + inline ExternalRefCountData() + { + QBasicAtomicInt proto = Q_BASIC_ATOMIC_INITIALIZER(1); + weakref = strongref = proto; + } + inline ExternalRefCountData(Qt::Initialization) { } + virtual inline ~ExternalRefCountData() { Q_ASSERT(!weakref); Q_ASSERT(strongref <= 0); } virtual inline bool destroy() { return false; } + +#ifndef QT_NO_QOBJECT + Q_CORE_EXPORT static ExternalRefCountData *getAndRef(const QObject *); +#endif }; // sizeof(ExternalRefCount) = 12 (32-bit) / 16 (64-bit) @@ -376,7 +385,7 @@ namespace QtSharedPointer { tmp = o->strongref; // failed, try again } - if (tmp) + if (tmp > 0) o->weakref.ref(); else o = 0; @@ -495,6 +504,15 @@ public: inline QWeakPointer() : d(0), value(0) { } inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; } + + // special constructor that is enabled only if X derives from QObject + template <class X> + inline QWeakPointer(X *ptr) : d(ptr ? d->getAndRef(ptr) : 0), value(ptr) + { } + template <class X> + inline QWeakPointer &operator=(X *ptr) + { return *this = QWeakPointer(ptr); } + inline QWeakPointer(const QWeakPointer<T> &o) : d(o.d), value(o.value) { if (d) d->weakref.ref(); } inline QWeakPointer<T> &operator=(const QWeakPointer<T> &o) |