From bdc6badde26d7543618561b51c4f76dec24e66f3 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 12 Aug 2009 10:37:45 +0200 Subject: usage of Q_OS_WINCE fixed There's no QT_OS_WINCE define. Reviewed-by: mauricek --- src/gui/kernel/qkeymapper_win.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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; -- cgit v0.12 From 62aa09a47cc226518d42f1b3b2337fdcb440da33 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Tue, 11 Aug 2009 15:45:27 +0200 Subject: Phonon: On windows, cross fading was broken --- src/3rdparty/phonon/ds9/mediaobject.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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())) { -- cgit v0.12 From b3b2bc3f190d80e30b968648dd91048df67b8a50 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 12 Aug 2009 10:33:33 +0200 Subject: Possible Dead lock in the destructor of QObject The problem was that we were locking a mutex that was global to thread to remove posted events associated with a QObject from the posted event list. We were also immediately deleting those events. If that triggers the deletion of another QObject, you would then trigger a dead-lock. Task-number: 259514 Reviewed-by: brad Reviewed-by: ogoffart --- src/corelib/kernel/qcoreapplication.cpp | 18 ++++++++++-------- src/corelib/kernel/qcoreapplication_p.h | 1 - src/corelib/kernel/qobject.cpp | 5 +---- tests/auto/qobject/tst_qobject.cpp | 18 ++++++++++++++++++ 4 files changed, 29 insertions(+), 13 deletions(-) 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 #include #include +#include #include #include @@ -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 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(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/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" -- cgit v0.12 From c8563ec79f01ec54a03bb2fdbba11a73a01370f7 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 6 Aug 2009 16:17:44 +0200 Subject: Doc: explain the use of QWeakPointer for tracking QObjects Explain the difference to QPointer and why QWeakPointer should be used instead. Reviewed-by: Trust Me --- src/corelib/tools/qsharedpointer.cpp | 109 ++++++++++++++++++++++++++++++----- src/corelib/tools/qsharedpointer.h | 3 + 2 files changed, 98 insertions(+), 14 deletions(-) diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 644ccc3..f793f26 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 &other) Makes this object share \a other's pointer. The current pointer 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 operator=(const QWeakPointer &other); QWeakPointer operator=(const QSharedPointer &other); + QWeakPointer(const QObject *other); + QWeakPointer operator=(const QObject *other); + T *data() const; void clear(); -- cgit v0.12 From 171d92dc8b800b24d28c7b4abf34d6961763bbf4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 12 Aug 2009 11:03:49 +0200 Subject: Autotest: make sure we can't create QWeakPointer from a QObject in destruction. This test only works in debug mode --- src/corelib/tools/qsharedpointer.cpp | 2 ++ tests/auto/qsharedpointer/tst_qsharedpointer.cpp | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index f793f26..e3e1db6 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -977,6 +977,8 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge { Q_ASSERT(obj); QObjectPrivate *d = QObjectPrivate::get(const_cast(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/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 weak = ptr;\n" // this makes the object unmanaged "QSharedPointer 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 weak = parent(); }\n" + "};\n" + "QObject obj;\n" + "new DerivedFromQObject(&obj);"; +#endif } void tst_QSharedPointer::invalidConstructs() -- cgit v0.12 From 3111f3c31627466d35317cceeb535c7679f4d3fa Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 6 Aug 2009 16:28:44 +0200 Subject: Add the typedefs to QSharedPointer and QWeakPointer to make template usage simpler. For example, this allows writing code like: template typename Pointer::pointer getPointer(constPointer &p) { return p.data(); } and that code will work for both QSharedPointer and QWeakPointer. Reviewed-by: Harald Fernengel Also add an operator- to make pointer operations possible. --- src/corelib/tools/qsharedpointer_impl.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) 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 &ptr1, const QWeakPointer &ptr2) return ptr2 != ptr1; } +template +Q_INLINE_TEMPLATE typename T::difference_type operator-(const QSharedPointer &ptr1, const QSharedPointer &ptr2) +{ + return ptr1.data() - ptr2.data(); +} + template Q_INLINE_TEMPLATE QWeakPointer QSharedPointer::toWeakRef() const { -- cgit v0.12 From 711f3691231ede6d8bf4e04f4dd8eb528655e115 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 12 Aug 2009 11:17:04 +0200 Subject: fix decoration of DontShowOnScreen widgets on Windows CE Widgets with the WA_DontShowOnScreen attribute must not have a window decoration. Autotest: tst_QWidget::initialPosForDontShowOnScreenWidgets Reviewed-by: thartman --- src/gui/kernel/qwidget_wince.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; -- cgit v0.12