diff options
author | Jason McDonald <jason.mcdonald@nokia.com> | 2009-08-12 09:36:47 (GMT) |
---|---|---|
committer | Jason McDonald <jason.mcdonald@nokia.com> | 2009-08-12 09:36:47 (GMT) |
commit | e02769f81c0d7ca9585b2fd9ba58d901db513f8c (patch) | |
tree | cb33782a53331cd4d18c863f8b3180124ea304d4 | |
parent | e81dd49a60f8058b8b142b1c6ed87526671abed9 (diff) | |
parent | 711f3691231ede6d8bf4e04f4dd8eb528655e115 (diff) | |
download | Qt-e02769f81c0d7ca9585b2fd9ba58d901db513f8c.zip Qt-e02769f81c0d7ca9585b2fd9ba58d901db513f8c.tar.gz Qt-e02769f81c0d7ca9585b2fd9ba58d901db513f8c.tar.bz2 |
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt
-rw-r--r-- | src/3rdparty/phonon/ds9/mediaobject.cpp | 3 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 18 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication_p.h | 1 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 5 | ||||
-rw-r--r-- | src/corelib/tools/qsharedpointer.cpp | 111 | ||||
-rw-r--r-- | src/corelib/tools/qsharedpointer.h | 3 | ||||
-rw-r--r-- | src/corelib/tools/qsharedpointer_impl.h | 21 | ||||
-rw-r--r-- | src/gui/kernel/qkeymapper_win.cpp | 4 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_wince.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qobject/tst_qobject.cpp | 18 | ||||
-rw-r--r-- | tests/auto/qsharedpointer/tst_qsharedpointer.cpp | 15 |
11 files changed, 170 insertions, 31 deletions
diff --git a/src/3rdparty/phonon/ds9/mediaobject.cpp b/src/3rdparty/phonon/ds9/mediaobject.cpp index 22f1527..de2078a 100644 --- a/src/3rdparty/phonon/ds9/mediaobject.cpp +++ b/src/3rdparty/phonon/ds9/mediaobject.cpp @@ -512,7 +512,8 @@ namespace Phonon qSwap(m_graphs[0], m_graphs[1]); //swap the graphs - m_graphs[1]->stop(); //make sure we stop the previous graph + if (m_transitionTime >= 0) + m_graphs[1]->stop(); //make sure we stop the previous graph if (currentGraph()->mediaSource().type() != Phonon::MediaSource::Invalid && catchComError(currentGraph()->renderResult())) { diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index b90f5c7..86221a1 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -60,6 +60,7 @@ #include <qthreadstorage.h> #include <private/qthread_p.h> #include <qlibraryinfo.h> +#include <qvarlengtharray.h> #include <private/qfactoryloader_p.h> #include <private/qfunctions_p.h> @@ -1353,13 +1354,10 @@ void QCoreApplication::removePostedEvents(QObject *receiver, int eventType) // for this object. if (receiver && !receiver->d_func()->postedEvents) return; - QCoreApplicationPrivate::removePostedEvents_unlocked(receiver, eventType, data); -} -void QCoreApplicationPrivate::removePostedEvents_unlocked(QObject *receiver, - int eventType, - QThreadData *data) -{ + //we will collect all the posted events for the QObject + //and we'll delete after the mutex was unlocked + QVarLengthArray<QEvent*> events; int n = data->postEventList.size(); int j = 0; @@ -1374,7 +1372,7 @@ void QCoreApplicationPrivate::removePostedEvents_unlocked(QObject *receiver, pe.receiver->d_func()->removePendingChildInsertedEvents(0); #endif pe.event->posted = false; - delete pe.event; + events.append(pe.event); const_cast<QPostEvent &>(pe).event = 0; } else if (!data->postEventList.recursion) { if (i != j) @@ -1393,8 +1391,12 @@ void QCoreApplicationPrivate::removePostedEvents_unlocked(QObject *receiver, // truncate list data->postEventList.erase(data->postEventList.begin() + j, data->postEventList.end()); } -} + locker.unlock(); + for (int i = 0; i < events.count(); ++i) { + delete events[i]; + } +} /*! Removes \a event from the queue of posted events, and emits a diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index bb94cbb..ef776c7 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -90,7 +90,6 @@ public: static QThread *mainThread(); static bool checkInstance(const char *method); static void sendPostedEvents(QObject *receiver, int event_type, QThreadData *data); - static void removePostedEvents_unlocked(QObject *receiver, int type, QThreadData *data); #if !defined (QT_NO_DEBUG) || defined (QT_MAC_FRAMEWORK_BUILD) void checkReceiverThread(QObject *receiver); diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 3902825..2afab1a 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -896,10 +896,7 @@ QObject::~QObject() qt_removeObject(this); - QMutexLocker locker2(&d->threadData->postEventList.mutex); - if (d->postedEvents > 0) - QCoreApplicationPrivate::removePostedEvents_unlocked(this, 0, d->threadData); - locker2.unlock(); + QCoreApplication::removePostedEvents(this); if (d->parent) // remove it from parent object d->setParent_helper(0); diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 644ccc3..e3e1db6 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -98,15 +98,14 @@ access made to the data being guarded: if it's a non-const access, it creates a copy atomically for the operation to complete. - QExplicitlySharedDataPointer behaves like QSharedDataPointer, - except that it only detaches if - QExplicitlySharedDataPointer::detach() is explicitly called. + QExplicitlySharedDataPointer is a variant of QSharedDataPointer, except + that it only detaches if QExplicitlySharedDataPointer::detach() is + explicitly called (hence the name). - Finally, QPointer holds a pointer to a QObject-derived object, but - it does so weakly. QPointer is similar, in that behaviour, to - QWeakPointer: it does not allow you to prevent the object from - being destroyed. All you can do is query whether it has been - destroyed or not. + Finally, QPointer holds a pointer to a QObject-derived object, but it + does so weakly. QPointer can be replaced by QWeakPointer in almost all + cases, since they have the same functionality. See + \l{QWeakPointer#tracking-qobject} for more information. \sa QSharedDataPointer, QWeakPointer */ @@ -123,12 +122,65 @@ directly, but it can be used to verify if the pointer has been deleted or not in another context. - QWeakPointer objects can only be created by assignment - from a QSharedPointer. - - To access the pointer that QWeakPointer is tracking, you - must first create a QSharedPointer object and verify if the pointer - is null or not. See QWeakPointer::toStrongRef() for more information. + QWeakPointer objects can only be created by assignment from a + QSharedPointer. The exception is pointers derived from QObject: in that + case, QWeakPointer serves as a replacement to QPointer. + + It's important to note that QWeakPointer provides no automatic casting + operators to prevent mistakes from happening. Even though QWeakPointer + tracks a pointer, it should not be considered a pointer itself, since it + doesn't guarantee that the pointed object remains valid. + + Therefore, to access the pointer that QWeakPointer is tracking, you must + first promote it to QSharedPointer and verify if the resulting object is + null or not. QSharedPointer guarantees that the object isn't deleted, so + if you obtain a non-null object, you may use the pointer. See + QWeakPointer::toStrongRef() for more an example. + + QWeakPointer also provides the QWeakPointer::data() method that returns + the tracked pointer without ensuring that it remains valid. This function + is provided if you can guarantee by external means that the object will + not get deleted (or if you only need the pointer value) and the cost of + creating a QSharedPointer using toStrongRef() is too high. + + That function can also be used to obtain the tracked pointer for + QWeakPointers that cannot be promoted to QSharedPointer, such as those + created directly from a QObject pointer (not via QSharedPointer). + + \section1 Tracking QObject + + QWeakPointer can be used to track deletion classes derives from QObject, + even if they are not managed by QSharedPointer. When used in that role, + QWeakPointer replaces the older QPointer in all use-cases. QWeakPointer + is also more efficient than QPointer, so it should be preferred in all + new code. + + To do that, QWeakPointer provides a special constructor that is only + available if the template parameter \tt T is either QObject or a class + deriving from it. Trying to use that constructor if \tt T does not derive + from QObject will result in compilation errors. + + To obtain the QObject being tracked by QWeakPointer, you must use the + QWeakPointer::data() function, but only if you can guarantee that the + object cannot get deleted by another context. It should be noted that + QPointer had the same constraint, so use of QWeakPointer forces you to + consider whether the pointer is still valid. + + QObject-derived classes can only be deleted in the thread they have + affinity to (which is the thread they were created in or moved to, using + QObject::moveToThread()). In special, QWidget-derived classes cannot be + created in non-GUI threads nor moved there. Therefore, guaranteeing that + the tracked QObject has affinity to the current thread is enough to also + guarantee that it won't be deleted asynchronously. + + Note that QWeakPointer's size and data layout do not match QPointer, so + it cannot replace that class in a binary-compatible manner. + + Care must also be taken with QWeakPointers created directly from QObject + pointers when dealing with code that was compiled with Qt versions prior + to 4.6. Those versions may not track the reference counters correctly, so + QWeakPointers created from QObject should never be passed to code that + hasn't been recompiled. \sa QSharedPointer */ @@ -412,6 +464,35 @@ */ /*! + \fn QWeakPointer::QWeakPointer(const QObject *obj) + \since 4.6 + + Creates a QWeakPointer that holds a weak reference directly to the + QObject \a obj. This constructor is only available if the template type + \tt T is QObject or derives from it (otherwise a compilation error will + result). + + You can use this constructor with any QObject, even if they were not + created with \l QSharedPointer. + + Note that QWeakPointers created this way on arbitrary QObjects usually + cannot be promoted to QSharedPointer. + + \sa QSharedPointer, QWeakPointer#tracking-qobject +*/ + +/*! + \fn QWeakPointer &QWeakPointer::operator=(const QObject *obj) + \since 4.6 + + Makes this QWeakPointer hold a weak reference to directly to the QObject + \a obj. This function is only available if the template type \tt T is + QObject or derives from it. + + \sa QWeakPointer#tracking-qobject +*/ + +/*! \fn QWeakPointer &QWeakPointer::operator=(const QWeakPointer<T> &other) Makes this object share \a other's pointer. The current pointer @@ -896,6 +977,8 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge { Q_ASSERT(obj); QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj)); + Q_ASSERT_X(!d->wasDeleted, "QWeakPointer", "Detected QWeakPointer creation in a QObject being deleted"); + ExternalRefCountData *that = d->sharedRefcount; if (that) { that->weakref.ref(); diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h index e0fe3b1..332883a 100644 --- a/src/corelib/tools/qsharedpointer.h +++ b/src/corelib/tools/qsharedpointer.h @@ -115,6 +115,9 @@ public: QWeakPointer<T> operator=(const QWeakPointer<T> &other); QWeakPointer<T> operator=(const QSharedPointer<T> &other); + QWeakPointer(const QObject *other); + QWeakPointer<T> operator=(const QObject *other); + T *data() const; void clear(); diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 7b3239b..ba479f9 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -121,6 +121,13 @@ namespace QtSharedPointer { typedef T *Basic:: *RestrictedBool; public: typedef T Type; + typedef T element_type; + typedef T value_type; + typedef value_type *pointer; + typedef const value_type *const_pointer; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef ptrdiff_t difference_type; inline T *data() const { return value; } inline bool isNull() const { return !data(); } @@ -490,6 +497,14 @@ class QWeakPointer typedef QtSharedPointer::ExternalRefCountData Data; public: + typedef T element_type; + typedef T value_type; + typedef value_type *pointer; + typedef const value_type *const_pointer; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef ptrdiff_t difference_type; + 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(); } @@ -634,6 +649,12 @@ bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) return ptr2 != ptr1; } +template <class T, class X> +Q_INLINE_TEMPLATE typename T::difference_type operator-(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) +{ + return ptr1.data() - ptr2.data(); +} + template <class T> Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const { diff --git a/src/gui/kernel/qkeymapper_win.cpp b/src/gui/kernel/qkeymapper_win.cpp index b094784..36abf86 100644 --- a/src/gui/kernel/qkeymapper_win.cpp +++ b/src/gui/kernel/qkeymapper_win.cpp @@ -770,7 +770,7 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool bool isNumpad = (msg.wParam >= VK_NUMPAD0 && msg.wParam <= VK_NUMPAD9); quint32 nModifiers = 0; -#if defined(QT_OS_WINCE) +#if defined(Q_OS_WINCE) nModifiers |= (GetKeyState(VK_SHIFT ) < 0 ? ShiftAny : 0); nModifiers |= (GetKeyState(VK_CONTROL) < 0 ? ControlAny : 0); nModifiers |= (GetKeyState(VK_MENU ) < 0 ? AltAny : 0); @@ -790,7 +790,7 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool nModifiers |= (GetKeyState(VK_CAPITAL ) & 0x01 ? CapsLock : 0); nModifiers |= (GetKeyState(VK_NUMLOCK ) & 0x01 ? NumLock : 0); nModifiers |= (GetKeyState(VK_SCROLL ) & 0x01 ? ScrollLock : 0); -#endif // QT_OS_WINCE +#endif // Q_OS_WINCE if (msg.lParam & ExtendedKey) nModifiers |= msg.lParam & ExtendedKey; diff --git a/src/gui/kernel/qwidget_wince.cpp b/src/gui/kernel/qwidget_wince.cpp index 54b9dcd..bcc9cfd 100644 --- a/src/gui/kernel/qwidget_wince.cpp +++ b/src/gui/kernel/qwidget_wince.cpp @@ -193,7 +193,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO int exsty = WS_EX_NOPARENTNOTIFY; if (topLevel) { - if (!(flags & Qt::FramelessWindowHint) && !tool) + if (!(flags & Qt::FramelessWindowHint) && !tool && !q->testAttribute(Qt::WA_DontShowOnScreen)) style = (WS_OVERLAPPED) | WS_SYSMENU; else style = WS_POPUP; diff --git a/tests/auto/qobject/tst_qobject.cpp b/tests/auto/qobject/tst_qobject.cpp index 2823c71..bb00a0b 100644 --- a/tests/auto/qobject/tst_qobject.cpp +++ b/tests/auto/qobject/tst_qobject.cpp @@ -119,6 +119,7 @@ private slots: void qobjectConstCast(); void uniqConnection(); void interfaceIid(); + void deleteQObjectWhenDeletingEvent(); protected: }; @@ -2898,5 +2899,22 @@ void tst_QObject::interfaceIid() QByteArray()); } +void tst_QObject::deleteQObjectWhenDeletingEvent() +{ + //this is related to task 259514 + //before the fix this used to dead lock when the QObject from the event was destroyed + + struct MyEvent : public QEvent + { + MyEvent() : QEvent(QEvent::User) { } + QObject obj; + }; + + QObject o; + QApplication::postEvent(&o, new MyEvent); + QCoreApplication::removePostedEvents(&o); // here you would get a deadlock +} + + QTEST_MAIN(tst_QObject) #include "tst_qobject.moc" diff --git a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp index 6bc3aa0..58e5401 100644 --- a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp @@ -1593,6 +1593,21 @@ void tst_QSharedPointer::invalidConstructs_data() << "QObject *ptr = new QObject;\n" "QWeakPointer<QObject> weak = ptr;\n" // this makes the object unmanaged "QSharedPointer<QObject> shared(ptr);\n"; + +#ifndef QT_NO_DEBUG + // this tests a Q_ASSERT, so it is only valid in debug mode + // the DerivedFromQObject destructor below creates a QWeakPointer from parent(). + // parent() is not 0 in the current Qt implementation, but has started destruction, + // so the code should detect that issue + QTest::newRow("shared-pointer-from-qobject-in-destruction") + << &QTest::QExternalTest::tryRunFail + << "class DerivedFromQObject: public QObject { public:\n" + " DerivedFromQObject(QObject *parent): QObject(parent) {}\n" + " ~DerivedFromQObject() { QWeakPointer<QObject> weak = parent(); }\n" + "};\n" + "QObject obj;\n" + "new DerivedFromQObject(&obj);"; +#endif } void tst_QSharedPointer::invalidConstructs() |