diff options
author | Jason Barron <jbarron@trolltech.com> | 2009-08-10 06:56:35 (GMT) |
---|---|---|
committer | Jason Barron <jbarron@trolltech.com> | 2009-08-10 06:56:35 (GMT) |
commit | f61ec84fc296c6f70011e30788ee511d6b6a18c6 (patch) | |
tree | 54b3b81ac83570e65dc9b44b6756005f6ba1efde /src/corelib | |
parent | cc0a411e5e874aa224c26298a109973cb15ea291 (diff) | |
parent | d13418effc5f00474541ae513a30c9a42c2a1cb3 (diff) | |
download | Qt-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.cpp | 12 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 16 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.cpp | 16 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.h | 1 | ||||
-rw-r--r-- | src/corelib/tools/qsharedpointer.cpp | 54 | ||||
-rw-r--r-- | src/corelib/tools/qsharedpointer.h | 1 | ||||
-rw-r--r-- | src/corelib/tools/qsharedpointer_impl.h | 100 |
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 |