summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorJason Barron <jbarron@trolltech.com>2009-08-10 06:56:35 (GMT)
committerJason Barron <jbarron@trolltech.com>2009-08-10 06:56:35 (GMT)
commitf61ec84fc296c6f70011e30788ee511d6b6a18c6 (patch)
tree54b3b81ac83570e65dc9b44b6756005f6ba1efde /src/corelib
parentcc0a411e5e874aa224c26298a109973cb15ea291 (diff)
parentd13418effc5f00474541ae513a30c9a42c2a1cb3 (diff)
downloadQt-f61ec84fc296c6f70011e30788ee511d6b6a18c6.zip
Qt-f61ec84fc296c6f70011e30788ee511d6b6a18c6.tar.gz
Qt-f61ec84fc296c6f70011e30788ee511d6b6a18c6.tar.bz2
Merge commit 'qt/master-stable'
Conflicts: src/corelib/kernel/qobject.cpp src/corelib/tools/qsharedpointer_impl.h src/gui/widgets/qdatetimeedit.cpp src/gui/widgets/qlinecontrol.cpp src/gui/widgets/qlineedit.cpp tests/auto/qcssparser/qcssparser.pro tests/auto/qicoimageformat/tst_qicoimageformat.cpp tests/auto/qmultiscreen/qmultiscreen.pro tests/auto/qresourceengine/qresourceengine.pro tests/auto/qresourceengine/tst_qresourceengine.cpp tests/auto/qscriptv8testsuite/tst_qscriptv8testsuite.cpp
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/io/qprocess_unix.cpp12
-rw-r--r--src/corelib/kernel/qobject.cpp16
-rw-r--r--src/corelib/kernel/qobject_p.h2
-rw-r--r--src/corelib/kernel/qvariant.cpp16
-rw-r--r--src/corelib/kernel/qvariant.h1
-rw-r--r--src/corelib/tools/qsharedpointer.cpp54
-rw-r--r--src/corelib/tools/qsharedpointer.h1
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h100
8 files changed, 146 insertions, 56 deletions
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 607b734..168eac2 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -162,7 +162,17 @@ private:
QMap<int, QProcessInfo *> children;
};
-Q_GLOBAL_STATIC(QProcessManager, processManager)
+
+Q_GLOBAL_STATIC(QMutex, processManagerGlobalMutex)
+
+static QProcessManager *processManager() {
+ // The constructor of QProcessManager should be called only once
+ // so we cannot use Q_GLOBAL_STATIC directly for QProcessManager
+ QMutex *mutex = processManagerGlobalMutex();
+ QMutexLocker locker(mutex);
+ static QProcessManager processManager;
+ return &processManager;
+}
QProcessManager::QProcessManager()
{
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index e6947a0..0f8548a 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>
@@ -794,6 +795,18 @@ QObject::~QObject()
QObjectPrivate::clearGuards(this);
}
+ if (d->sharedRefcount) {
+ if (d->sharedRefcount->strongref > 0) {
+ qWarning("QObject: shared QObject was deleted directly. The program is malformed and may crash.");
+ // but continue deleting, it's too late to stop anyway
+ }
+
+ // indicate to all QWeakPointers that this QObject has now been deleted
+ d->sharedRefcount->strongref = 0;
+ if (!d->sharedRefcount->weakref.deref())
+ delete d->sharedRefcount;
+ }
+
QT_TRY {
emit destroyed(this);
if (d->declarativeData)
@@ -814,6 +827,7 @@ QObject::~QObject()
#endif
}
+
{
QMutex *signalSlotMutex = 0;
QT_TRY {
@@ -878,9 +892,9 @@ QObject::~QObject()
if (senderLists)
senderLists->dirty = true;
+ node = node->next;
if (needToUnlock)
m->unlock();
- node = node->next;
}
}
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index e58ee6c..5d17bfd 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 { struct 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/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 5016d3b..a7e4135 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -170,6 +170,9 @@ static void construct(QVariant::Private *x, const void *copy)
case QMetaType::Float:
x->data.f = copy ? *static_cast<const float*>(copy) : 0.0f;
break;
+ case QMetaType::QObjectStar:
+ x->data.o = copy ? *static_cast<QObject *const*>(copy) : 0;
+ break;
case QVariant::LongLong:
#if defined(Q_CC_RVCT)
// Using trinary operator with 64bit constants crashes when ran on Symbian device
@@ -284,6 +287,7 @@ static void clear(QVariant::Private *d)
case QVariant::ULongLong:
case QVariant::Double:
case QMetaType::Float:
+ case QMetaType::QObjectStar:
break;
case QVariant::Invalid:
case QVariant::UserType:
@@ -353,6 +357,7 @@ static bool isNull(const QVariant::Private *d)
case QVariant::Bool:
case QVariant::Double:
case QMetaType::Float:
+ case QMetaType::QObjectStar:
break;
}
return d->is_null;
@@ -446,6 +451,8 @@ static bool compare(const QVariant::Private *a, const QVariant::Private *b)
return a->data.d == b->data.d;
case QMetaType::Float:
return a->data.f == b->data.f;
+ case QMetaType::QObjectStar:
+ return a->data.o == b->data.o;
case QVariant::Date:
return *v_cast<QDate>(a) == *v_cast<QDate>(b);
case QVariant::Time:
@@ -1075,6 +1082,9 @@ static void streamDebug(QDebug dbg, const QVariant &v)
case QMetaType::Float:
dbg.nospace() << qVariantValue<float>(v);
break;
+ case QMetaType::QObjectStar:
+ dbg.nospace() << qVariantValue<QObject *>(v);
+ break;
case QVariant::Double:
dbg.nospace() << v.toDouble();
break;
@@ -1388,7 +1398,7 @@ void QVariant::create(int type, const void *copy)
QVariant::~QVariant()
{
- if (d.type > Char && d.type != QMetaType::Float && (!d.is_shared || !d.data.shared->ref.deref()))
+ if (d.type > Char && d.type != QMetaType::Float && d.type != QMetaType::QObjectStar && (!d.is_shared || !d.data.shared->ref.deref()))
handler->clear(&d);
}
@@ -1404,7 +1414,7 @@ QVariant::QVariant(const QVariant &p)
{
if (d.is_shared) {
d.data.shared->ref.ref();
- } else if (p.d.type > Char && p.d.type != QMetaType::Float) {
+ } else if (p.d.type > Char && p.d.type != QMetaType::Float && p.d.type != QMetaType::QObjectStar) {
handler->construct(&d, p.constData());
d.is_null = p.d.is_null;
}
@@ -1760,7 +1770,7 @@ QVariant& QVariant::operator=(const QVariant &variant)
if (variant.d.is_shared) {
variant.d.data.shared->ref.ref();
d = variant.d;
- } else if (variant.d.type > Char && variant.d.type != QMetaType::Float) {
+ } else if (variant.d.type > Char && variant.d.type != QMetaType::Float && variant.d.type != QMetaType::QObjectStar) {
d.type = variant.d.type;
handler->construct(&d, variant.constData());
d.is_null = variant.d.is_null;
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index a68939d..4489e95 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -358,6 +358,7 @@ class Q_CORE_EXPORT QVariant
float f;
qlonglong ll;
qulonglong ull;
+ QObject *o;
void *ptr;
PrivateShared *shared;
} data;
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index f7b014e..4fecc9a 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -370,7 +370,7 @@
Returns a weak reference object that shares the pointer referenced
by this object.
- \sa QWeakPointer::QWeakPointer(const QSharedPointer<T> &)
+ \sa QWeakPointer::QWeakPointer()
*/
/*!
@@ -558,7 +558,7 @@
qDebug() << "The value has already been deleted";
\endcode
- \sa QSharedPointer::QSharedPointer(const QWeakPointer<T> &)
+ \sa QSharedPointer::QSharedPointer()
*/
/*!
@@ -869,6 +869,56 @@
#include <qset.h>
#include <qmutex.h>
+#if !defined(QT_NO_QOBJECT)
+#include "../kernel/qobject_p.h"
+
+/*!
+ \internal
+ This function is called for a just-created QObject \a obj, to enable
+ the use of QSharedPointer and QWeakPointer.
+
+ When QSharedPointer is active in a QObject, the object must not be deleted
+ directly: the lifetime is managed by the QSharedPointer object. In that case,
+ the deleteLater() and parent-child relationship in QObject only decrease
+ the strong reference count, instead of deleting the object.
+*/
+void QtSharedPointer::ExternalRefCountData::setQObjectShared(const QObject *obj, bool)
+{
+ Q_ASSERT(obj);
+ QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj));
+
+ if (d->sharedRefcount)
+ qFatal("QSharedPointer: pointer %p already has reference counting", obj);
+ d->sharedRefcount = this;
+
+ // QObject decreases the refcount too, so increase it up
+ weakref.ref();
+}
+
+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.h b/src/corelib/tools/qsharedpointer.h
index abd83ad..2f86ce7 100644
--- a/src/corelib/tools/qsharedpointer.h
+++ b/src/corelib/tools/qsharedpointer.h
@@ -115,6 +115,7 @@ public:
QWeakPointer<T> operator=(const QWeakPointer<T> &other);
QWeakPointer<T> operator=(const QSharedPointer<T> &other);
+ T *data() const;
void clear();
QSharedPointer<T> toStrongRef() const;
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index 25373b3..76a5abb 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -94,7 +94,6 @@ namespace QtSharedPointer {
template <class T> class InternalRefCount;
template <class T> class ExternalRefCount;
- template <class X, class T> QSharedPointer<X> strongRefFromWeakHelper(const QWeakPointer<T> &, X*);
template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
// used in debug mode to verify the reuse of pointers
@@ -137,21 +136,10 @@ namespace QtSharedPointer {
inline T *operator->() const { return data(); }
protected:
- inline Basic() : value(0) { }
+ inline Basic(T *ptr = 0) : value(ptr) { }
+ inline Basic(Qt::Initialization) { }
// ~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)
{
value = ptr;
@@ -168,13 +156,24 @@ 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 *);
+ Q_CORE_EXPORT void setQObjectShared(const QObject *, bool enable);
+#endif
+ inline void setQObjectShared(...) { }
};
// sizeof(ExternalRefCount) = 12 (32-bit) / 16 (64-bit)
@@ -309,9 +308,10 @@ namespace QtSharedPointer {
#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
internalConstruct<void (*)(T *)>(ptr, normalDeleter);
#else
- Q_ASSERT(!d);
if (ptr)
d = new Data;
+ else
+ d = 0;
internalFinishConstruction(ptr);
#endif
}
@@ -319,9 +319,10 @@ namespace QtSharedPointer {
template <typename Deleter>
inline void internalConstruct(T *ptr, Deleter deleter)
{
- Q_ASSERT(!d);
if (ptr)
d = ExternalRefCountWithCustomDeleter<T, Deleter>::create(ptr, deleter);
+ else
+ d = 0;
internalFinishConstruction(ptr);
}
@@ -335,15 +336,20 @@ namespace QtSharedPointer {
inline void internalFinishConstruction(T *ptr)
{
Basic<T>::internalConstruct(ptr);
+ if (ptr) d->setQObjectShared(ptr, true);
#ifdef QT_SHAREDPOINTER_TRACK_POINTERS
if (ptr) internalSafetyCheckAdd2(d, ptr);
#endif
}
inline ExternalRefCount() : d(0) { }
- inline ~ExternalRefCount() { if (d && !deref()) delete d; }
+ inline ExternalRefCount(Qt::Initialization i) : Basic<T>(i) { }
inline ExternalRefCount(const ExternalRefCount<T> &other) : Basic<T>(other), d(other.d)
{ if (d) ref(); }
+ template <class X>
+ inline ExternalRefCount(const ExternalRefCount<X> &other) : Basic<T>(other.value), d(other.d)
+ { if (d) ref(); }
+ inline ~ExternalRefCount() { if (d && !deref()) delete d; }
template <class X>
inline void internalCopy(const ExternalRefCount<X> &other)
@@ -357,23 +363,19 @@ namespace QtSharedPointer {
delete this->value;
}
- private:
#if defined(Q_NO_TEMPLATE_FRIENDS)
public:
#else
template <class X> friend class ExternalRefCount;
template <class X> friend class QWeakPointer;
template <class X, class Y> friend QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
- template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::strongRefFromWeakHelper(const QWeakPointer<Y> &src, X *);
#endif
inline void internalSet(Data *o, T *actual)
{
- if (d == o) return;
if (o) {
- Basic<T>::verifyReconstruction(actual);
-
// increase the strongref, but never up from zero
+ // or less (-1 is used by QWeakPointer on untracked QObject)
register int tmp = o->strongref;
while (tmp > 0) {
// try to increment from "tmp" to "tmp + 1"
@@ -382,7 +384,7 @@ namespace QtSharedPointer {
tmp = o->strongref; // failed, try again
}
- if (tmp)
+ if (tmp > 0)
o->weakref.ref();
else
o = 0;
@@ -393,7 +395,6 @@ namespace QtSharedPointer {
this->value = d && d->strongref ? actual : 0;
}
- protected:
Data *d;
private:
@@ -409,7 +410,8 @@ public:
inline QSharedPointer() { }
// inline ~QSharedPointer() { }
- inline explicit QSharedPointer(T *ptr) { BaseClass::internalConstruct(ptr); }
+ inline explicit QSharedPointer(T *ptr) : BaseClass(Qt::Uninitialized)
+ { internalConstruct(ptr); }
template <typename Deleter>
inline QSharedPointer(T *ptr, Deleter d) { BaseClass::internalConstruct(ptr, d); }
@@ -421,13 +423,9 @@ public:
return *this;
}
- inline QSharedPointer(const QWeakPointer<T> &other)
- { *this = QtSharedPointer::strongRefFromWeakHelper(other, static_cast<T*>(0)); }
- inline QSharedPointer<T> &operator=(const QWeakPointer<T> &other)
- { *this = QtSharedPointer::strongRefFromWeakHelper(other, static_cast<T*>(0)); return *this; }
-
template <class X>
- inline QSharedPointer(const QSharedPointer<X> &other) { *this = other; }
+ inline QSharedPointer(const QSharedPointer<X> &other) : BaseClass(other)
+ { }
template <class X>
inline QSharedPointer<T> &operator=(const QSharedPointer<X> &other)
@@ -438,12 +436,12 @@ public:
}
template <class X>
- inline QSharedPointer(const QWeakPointer<X> &other)
- { *this = QtSharedPointer::strongRefFromWeakHelper(other, static_cast<T *>(0)); }
+ inline QSharedPointer(const QWeakPointer<X> &other) : BaseClass(Qt::Uninitialized)
+ { this->d = 0; *this = other; }
template <class X>
inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
- { *this = strongRefFromWeakHelper(other, static_cast<T *>(0)); return *this; }
+ { internalSet(other.d, other.value); return *this; }
template <class X>
QSharedPointer<X> staticCast() const
@@ -475,10 +473,13 @@ public:
QWeakPointer<T> toWeakRef() const;
+protected:
+ inline QSharedPointer(Qt::Initialization i) : BaseClass(i) {}
+
public:
static inline QSharedPointer<T> create()
{
- QSharedPointer<T> result;
+ QSharedPointer<T> result(Qt::Uninitialized);
result.internalCreate();
// now initialize the data
@@ -508,6 +509,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)
@@ -559,7 +569,7 @@ public:
template <class X>
inline bool operator==(const QSharedPointer<X> &o) const
- { return d == o.d && value == static_cast<const T *>(o.data()); }
+ { return d == o.d; }
template <class X>
inline bool operator!=(const QSharedPointer<X> &o) const
@@ -574,7 +584,7 @@ private:
#if defined(Q_NO_TEMPLATE_FRIENDS)
public:
#else
- template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::strongRefFromWeakHelper(const QWeakPointer<Y> &src, X *);
+ template <class X> friend class QSharedPointer;
#endif
inline void internalSet(Data *o, T *actual)
@@ -651,14 +661,6 @@ namespace QtSharedPointer {
result.internalSet(src.d, ptr);
return result;
}
- template <class X, class T>
- Q_INLINE_TEMPLATE QSharedPointer<X> strongRefFromWeakHelper
- (const QT_PREPEND_NAMESPACE(QWeakPointer<T>) &src, X *)
- {
- QSharedPointer<X> result;
- result.internalSet(src.d, src.value);
- return result;
- }
}
// cast operators