summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@nokia.com>2009-08-03 16:49:16 (GMT)
committerThiago Macieira <thiago.macieira@nokia.com>2009-08-05 13:16:28 (GMT)
commit021a116d48a1df3624ad2221a418f1585f7ec4f8 (patch)
tree9c4800098b95447c8f9941916be57f4d2e70663c /src/corelib/kernel
parent435bbd4be73768f617e4a4083a345d1d8d62daa3 (diff)
downloadQt-021a116d48a1df3624ad2221a418f1585f7ec4f8.zip
Qt-021a116d48a1df3624ad2221a418f1585f7ec4f8.tar.gz
Qt-021a116d48a1df3624ad2221a418f1585f7ec4f8.tar.bz2
Add support for using QWeakPointer with QObject, replacing QPointer.
The problem with QPointer is that it's a simple QObject*. So the only way for QPointer to do what it's supposed to do is if the object it's pointing to clears all QPointers when getting deleted. That means the QObject must know each and every QPointer pointing to it. To make matters worse, QPointers can be deleted while the object they're pointing to also gets deleted. So deleting QObjects must do locking. The solution to the QPointer problem is that both QObject and the "QPointer" reference something outside the QObject. This way, QObject doesn't have to lock anything to destroy itself: it's simply setting a volatile integer to zero when it gets deleted. Since the integer is outside the QObject, the integer is also refcounted. It's also O(1), so there's no problem having as many "QPointer". The two-atomic-ints structure is exactly what QSharedPointer and QWeakPointer use internally. We just abuse this structure for QObject needs, setting the strong reference count to -1 to indicate that it's a QObject that cannot be managed by a QSharedPointer. But QWeakPointer can still work and replace QPointer neatly. Reviewed-by: Bradley T. Hughes Reviewed-by: Jarek Kobus
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qobject.cpp8
-rw-r--r--src/corelib/kernel/qobject_p.h2
2 files changed, 10 insertions, 0 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;
};