diff options
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 114 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.h | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 4 | ||||
-rw-r--r-- | src/corelib/thread/qmutex.cpp | 133 | ||||
-rw-r--r-- | src/corelib/thread/qmutex.h | 71 | ||||
-rw-r--r-- | src/corelib/thread/qmutex_p.h | 11 | ||||
-rw-r--r-- | src/corelib/thread/qmutex_unix.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/qmutex_win.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/qorderedmutexlocker_p.h | 14 | ||||
-rw-r--r-- | src/corelib/tools/qlist.h | 5 | ||||
-rw-r--r-- | src/gui/kernel/qwidget.cpp | 3 | ||||
-rw-r--r-- | tests/benchmarks/corelib/thread/qmutex/qmutex.pro | 6 | ||||
-rw-r--r-- | tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp | 131 |
13 files changed, 371 insertions, 127 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 8a4304e..c01df66 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -149,9 +149,11 @@ QObjectPrivate::QObjectPrivate(int version) postedEvents = 0; extraData = 0; connectedSignals[0] = connectedSignals[1] = 0; - inEventHandler = false; inThreadChangeEvent = false; +#ifdef QT_JAMBI_BUILD + inEventHandler = false; deleteWatch = 0; +#endif metaObject = 0; hasGuards = false; } @@ -159,8 +161,10 @@ QObjectPrivate::QObjectPrivate(int version) QObjectPrivate::~QObjectPrivate() { delete static_cast<QAbstractDynamicMetaObject*>(metaObject); +#ifdef QT_JAMBI_BUILD if (deleteWatch) *deleteWatch = 1; +#endif #ifndef QT_NO_USERDATA if (extraData) qDeleteAll(extraData->userData); @@ -169,6 +173,7 @@ QObjectPrivate::~QObjectPrivate() } +#ifdef QT_JAMBI_BUILD int *QObjectPrivate::setDeleteWatch(QObjectPrivate *d, int *w) { int *old = d->deleteWatch; d->deleteWatch = w; @@ -183,10 +188,7 @@ void QObjectPrivate::resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int dele if (oldWatch) *oldWatch = deleteWatch; } - - - - +#endif #ifdef QT3_SUPPORT void QObjectPrivate::sendPendingChildInsertedEvents() @@ -476,11 +478,6 @@ void QMetaObject::changeGuard(QObject **ptr, QObject *o) */ void QObjectPrivate::clearGuards(QObject *object) { - QObjectPrivate *priv = QObjectPrivate::get(object); - - if (!priv->hasGuards) - return; - GuardHash *hash = 0; QMutex *mutex = 0; QT_TRY { @@ -732,13 +729,15 @@ QObject::QObject(QObject *parent) d_ptr->q_ptr = this; d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current(); d->threadData->ref(); - QT_TRY { - if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) - parent = 0; - setParent(parent); - } QT_CATCH(...) { - d->threadData->deref(); - QT_RETHROW; + if (parent) { + QT_TRY { + if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) + parent = 0; + setParent(parent); + } QT_CATCH(...) { + d->threadData->deref(); + QT_RETHROW; + } } qt_addObject(this); } @@ -757,9 +756,11 @@ QObject::QObject(QObject *parent, const char *name) qt_addObject(d_ptr->q_ptr = this); d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current(); d->threadData->ref(); - if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) - parent = 0; - setParent(parent); + if (parent) { + if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) + parent = 0; + setParent(parent); + } setObjectName(QString::fromAscii(name)); } #endif @@ -773,21 +774,23 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent) d_ptr->q_ptr = this; d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current(); d->threadData->ref(); - QT_TRY { - if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) - parent = 0; - if (d->isWidget) { - if (parent) { - d->parent = parent; - d->parent->d_func()->children.append(this); + if (parent) { + QT_TRY { + if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) + parent = 0; + if (d->isWidget) { + if (parent) { + d->parent = parent; + d->parent->d_func()->children.append(this); + } + // no events sent here, this is done at the end of the QWidget constructor + } else { + setParent(parent); } - // no events sent here, this is done at the end of the QWidget constructor - } else { - setParent(parent); + } QT_CATCH(...) { + d->threadData->deref(); + QT_RETHROW; } - } QT_CATCH(...) { - d->threadData->deref(); - QT_RETHROW; } qt_addObject(this); } @@ -822,7 +825,7 @@ QObject::~QObject() d->wasDeleted = true; d->blockSig = 0; // unblock signals so we always emit destroyed() - if (!d->isWidget) { + if (d->hasGuards && !d->isWidget) { // set all QPointers for this object to zero - note that // ~QWidget() does this for us, so we don't have to do it twice QObjectPrivate::clearGuards(this); @@ -840,22 +843,16 @@ QObject::~QObject() delete d->sharedRefcount; } - QT_TRY { - emit destroyed(this); - } QT_CATCH(...) { - // all the signal/slots connections are still in place - if we don't - // quit now, we will crash pretty soon. - qWarning("Detected an unexpected exception in ~QObject while emitting destroyed()."); -#if defined(Q_BUILD_INTERNAL) && !defined(QT_NO_EXCEPTIONS) - struct AutotestException : public std::exception - { - const char *what() const throw() { return "autotest swallow"; } - } autotestException; - // throw autotestException; -#else - QT_RETHROW; -#endif + if (d->isSignalConnected(0)) { + QT_TRY { + emit destroyed(this); + } QT_CATCH(...) { + // all the signal/slots connections are still in place - if we don't + // quit now, we will crash pretty soon. + qWarning("Detected an unexpected exception in ~QObject while emitting destroyed()."); + QT_RETHROW; + } } if (d->declarativeData) @@ -893,7 +890,7 @@ QObject::~QObject() if (c->next) c->next->prev = c->prev; } if (needToUnlock) - m->unlock(); + m->unlockInline(); connectionList.first = c->nextConnectionList; delete c; @@ -917,7 +914,7 @@ QObject::~QObject() bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); //the node has maybe been removed while the mutex was unlocked in relock? if (!node || node->sender != sender) { - m->unlock(); + m->unlockInline(); continue; } node->receiver = 0; @@ -927,7 +924,7 @@ QObject::~QObject() node = node->next; if (needToUnlock) - m->unlock(); + m->unlockInline(); } } @@ -937,12 +934,6 @@ QObject::~QObject() d->threadData->eventDispatcher->unregisterTimers(this); } -#ifdef QT3_SUPPORT - d->pendingChildInsertedEvents.clear(); -#endif - - d->eventFilters.clear(); - if (!d->children.isEmpty()) d->deleteChildren(); @@ -1198,7 +1189,9 @@ bool QObject::event(QEvent *e) case QEvent::MetaCall: { +#ifdef QT_JAMBI_BUILD d_func()->inEventHandler = false; +#endif QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e); QObjectPrivate::Sender currentSender; currentSender.sender = const_cast<QObject*>(mce->sender()); @@ -1516,11 +1509,14 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData currentSender->ref = 0; currentSender = 0; +#ifdef QT_JAMBI_BUILD // the current event thread also shouldn't restore the delete watch inEventHandler = false; + if (deleteWatch) *deleteWatch = 1; deleteWatch = 0; +#endif // set new thread data targetData->ref(); @@ -2983,7 +2979,7 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, } if (needToUnlock) - receiverMutex->unlock(); + receiverMutex->unlockInline(); c->receiver = 0; diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 1b613a6..44e7ce5 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -109,7 +109,7 @@ public: uint ownObjectName : 1; uint sendChildEvents : 1; uint receiveChildEvents : 1; - uint inEventHandler : 1; + uint inEventHandler : 1; //only used if QT_JAMBI_BUILD uint inThreadChangeEvent : 1; uint hasGuards : 1; //true iff there is one or more QPointer attached to this object uint unused : 22; diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 4800e6a..35b4540 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -161,8 +161,10 @@ public: static inline void resetCurrentSender(QObject *receiver, Sender *currentSender, Sender *previousSender); +#ifdef QT_JAMBI_BUILD static int *setDeleteWatch(QObjectPrivate *d, int *newWatch); static void resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch); +#endif static void clearGuards(QObject *); static QObjectPrivate *get(QObject *o) { @@ -200,7 +202,9 @@ public: // these objects are all used to indicate that a QObject was deleted // plus QPointer, which keeps a separate list QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount; +#ifdef QT_JAMBI_BUILD int *deleteWatch; +#endif }; diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index 43df13a..eb6f729 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -130,7 +130,7 @@ QMutex::QMutex(RecursionMode mode) \warning Destroying a locked mutex may result in undefined behavior. */ QMutex::~QMutex() -{ delete d; } +{ delete static_cast<QMutexPrivate *>(d); } /*! Locks the mutex. If another thread has locked the mutex then this @@ -146,6 +146,7 @@ QMutex::~QMutex() */ void QMutex::lock() { + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); Qt::HANDLE self; if (d->recursive) { @@ -184,43 +185,7 @@ void QMutex::lock() bool isLocked = d->contenders == 0 && d->contenders.testAndSetAcquire(0, 1); if (!isLocked) { - int spinCount = 0; - int lastSpinCount = d->lastSpinCount; - - enum { AdditionalSpins = 20, SpinCountPenalizationDivisor = 4 }; - const int maximumSpinCount = lastSpinCount + AdditionalSpins; - - do { - if (spinCount++ > maximumSpinCount) { - // puts("spinning useless, sleeping"); - isLocked = d->contenders.fetchAndAddAcquire(1) == 0; - if (!isLocked) { -#ifndef QT_NO_DEBUG - if (d->owner == self) - qWarning() << "QMutex::lock: Deadlock detected in thread" << d->owner; -#endif - - // didn't get the lock, wait for it - isLocked = d->wait(); - Q_ASSERT_X(isLocked, "QMutex::lock", - "Internal error, infinite wait has timed out."); - - // don't need to wait for the lock anymore - d->contenders.deref(); - } - // decrease the lastSpinCount since we didn't actually get the lock by spinning - spinCount = -d->lastSpinCount / SpinCountPenalizationDivisor; - break; - } - - isLocked = d->contenders == 0 && d->contenders.testAndSetAcquire(0, 1); - } while (!isLocked); - - // adjust the last spin lock count - lastSpinCount = d->lastSpinCount; - d->lastSpinCount = spinCount >= 0 - ? qMax(lastSpinCount, spinCount) - : lastSpinCount + spinCount; + lockInternal(); } #ifndef QT_NO_DEBUG @@ -247,6 +212,7 @@ void QMutex::lock() */ bool QMutex::tryLock() { + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); Qt::HANDLE self; if (d->recursive) { @@ -310,6 +276,7 @@ bool QMutex::tryLock() */ bool QMutex::tryLock(int timeout) { + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); Qt::HANDLE self; if (d->recursive) { @@ -366,8 +333,13 @@ bool QMutex::tryLock(int timeout) */ void QMutex::unlock() { - Q_ASSERT_X(d->owner == QThread::currentThreadId(), "QMutex::unlock()", - "A mutex must be unlocked in the same thread that locked it."); + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); +#ifndef QT_NO_DEBUG + //note: if the mutex has been locked with (try)lockInline, d->owner could have not been set, and this would be a false warning + if ((d->owner || d->recursive) && d->owner != QThread::currentThreadId()) + qWarning("QMutex::unlock(): A mutex must be unlocked in the same thread that locked it."); +#endif + if (d->recursive) { if (!--d->count) { @@ -506,6 +478,87 @@ void QMutex::unlock() Use the constructor that takes a RecursionMode parameter instead. */ +/*! + \internal helper for lockInline() + */ +void QMutex::lockInternal() +{ + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); + int spinCount = 0; + int lastSpinCount = d->lastSpinCount; + + enum { AdditionalSpins = 20, SpinCountPenalizationDivisor = 4 }; + const int maximumSpinCount = lastSpinCount + AdditionalSpins; + +#ifndef QT_NO_DEBUG + Qt::HANDLE self = QThread::currentThreadId(); +#endif + + do { + if (spinCount++ > maximumSpinCount) { + // puts("spinning useless, sleeping"); + bool isLocked = d->contenders.fetchAndAddAcquire(1) == 0; + if (!isLocked) { +#ifndef QT_NO_DEBUG + if (d->owner == self) + qWarning() << "QMutex::lock: Deadlock detected in thread" << d->owner; +#endif + + // didn't get the lock, wait for it + isLocked = d->wait(); + Q_ASSERT_X(isLocked, "QMutex::lock", + "Internal error, infinite wait has timed out."); + + // don't need to wait for the lock anymore + d->contenders.deref(); + } + // decrease the lastSpinCount since we didn't actually get the lock by spinning + spinCount = -d->lastSpinCount / SpinCountPenalizationDivisor; + break; + } + } while (d->contenders != 0 || !d->contenders.testAndSetAcquire(0, 1)); + + // adjust the last spin lock count + lastSpinCount = d->lastSpinCount; + d->lastSpinCount = spinCount >= 0 + ? qMax(lastSpinCount, spinCount) + : lastSpinCount + spinCount; + +#ifndef QT_NO_DEBUG + d->owner = self; +#endif +} + +/*! + \internal +*/ +void QMutex::unlockInternal() +{ +#ifndef QT_NO_DEBUG + static_cast<QMutexPrivate *>(d)->owner = 0; +#endif + static_cast<QMutexPrivate *>(d)->wakeUp(); +} + +/*! + \fn QMutex::lockInline() + \internal + inline version of QMutex::lock() +*/ + +/*! + \fn QMutex::unlockInline() + \internal + inline version of QMutex::unlock() +*/ + +/*! + \fn QMutex::tryLockInline() + \internal + inline version of QMutex::tryLock() +*/ + + QT_END_NAMESPACE #endif // QT_NO_THREAD diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h index 509f300..710b794 100644 --- a/src/corelib/thread/qmutex.h +++ b/src/corelib/thread/qmutex.h @@ -43,6 +43,7 @@ #define QMUTEX_H #include <QtCore/qglobal.h> +#include <QtCore/qatomic.h> #include <new> QT_BEGIN_HEADER @@ -53,7 +54,8 @@ QT_MODULE(Core) #ifndef QT_NO_THREAD -class QMutexPrivate; +class QAtomicInt; +class QMutexData; class Q_CORE_EXPORT QMutex { @@ -66,10 +68,13 @@ public: explicit QMutex(RecursionMode mode = NonRecursive); ~QMutex(); - void lock(); - bool tryLock(); + void lock(); //### Qt5: make inline; + inline void lockInline(); + bool tryLock(); //### Qt5: make inline; bool tryLock(int timeout); - void unlock(); + inline bool tryLockInline(); + void unlock(); //### Qt5: make inline; + inline void unlockInline(); #if defined(QT3_SUPPORT) inline QT3_SUPPORT bool locked() @@ -86,9 +91,11 @@ public: #endif private: + void lockInternal(); + void unlockInternal(); Q_DISABLE_COPY(QMutex) - QMutexPrivate *d; + QMutexData *d; }; class Q_CORE_EXPORT QMutexLocker @@ -99,7 +106,7 @@ public: Q_ASSERT_X((reinterpret_cast<quintptr>(m) & quintptr(1u)) == quintptr(0), "QMutexLocker", "QMutex pointer is misaligned"); if (m) { - m->lock(); + m->lockInline(); val = reinterpret_cast<quintptr>(m) | quintptr(1u); } else { val = 0; @@ -111,7 +118,7 @@ public: { if ((val & quintptr(1u)) == quintptr(1u)) { val &= ~quintptr(1u); - mutex()->unlock(); + mutex()->unlockInline(); } } @@ -119,7 +126,7 @@ public: { if (val) { if ((val & quintptr(1u)) == quintptr(0u)) { - mutex()->lock(); + mutex()->lockInline(); val |= quintptr(1u); } } @@ -145,6 +152,46 @@ private: quintptr val; }; +class QMutexData +{ + public: + QAtomicInt contenders; + const uint recursive : 1; + uint reserved : 31; + protected: + QMutexData(QMutex::RecursionMode mode); + ~QMutexData(); +}; + +inline void QMutex::unlockInline() +{ + if (d->recursive) { + unlock(); + } else if (!d->contenders.testAndSetRelease(1, 0)) { + unlockInternal(); + } +} + +inline bool QMutex::tryLockInline() +{ + if (d->recursive) { + return tryLock(); + } else { + return d->contenders.testAndSetAcquire(0, 1); + } +} + +inline void QMutex::lockInline() +{ + if (d->recursive) { + lock(); + } else if(!tryLockInline()) { + lockInternal(); + } +} + + + #else // QT_NO_THREAD @@ -157,9 +204,11 @@ public: inline ~QMutex() {} static inline void lock() {} - static inline bool tryLock() { return true; } - static inline bool tryLock(int timeout) { Q_UNUSED(timeout); return true; } - static void unlock() {} + static inline void lockInline() {} + static inline bool tryLock(int timeout = 0) { Q_UNUSED(timeout); return true; } + static inline bool tryLockInline() { return true; } + static inline void unlock() {} + static inline void unlockInline() {} #if defined(QT3_SUPPORT) static inline QT3_SUPPORT bool locked() { return false; } diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h index dce162a..6126423 100644 --- a/src/corelib/thread/qmutex_p.h +++ b/src/corelib/thread/qmutex_p.h @@ -56,10 +56,11 @@ #include <QtCore/qglobal.h> #include <QtCore/qnamespace.h> +#include <QtCore/qmutex.h> QT_BEGIN_NAMESPACE -class QMutexPrivate { +class QMutexPrivate : public QMutexData { public: QMutexPrivate(QMutex::RecursionMode mode); ~QMutexPrivate(); @@ -68,8 +69,6 @@ public: bool wait(int timeout = -1); void wakeUp(); - const bool recursive; - QAtomicInt contenders; volatile int lastSpinCount; Qt::HANDLE owner; uint count; @@ -83,6 +82,12 @@ public: #endif }; +inline QMutexData::QMutexData(QMutex::RecursionMode mode) + : recursive(mode == QMutex::Recursive) +{} + +inline QMutexData::~QMutexData() {} + QT_END_NAMESPACE #endif // QMUTEX_P_H diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index a58368c..7e7ef22 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -63,7 +63,7 @@ static void report_error(int code, const char *where, const char *what) QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode) - : recursive(mode == QMutex::Recursive), contenders(0), lastSpinCount(0), owner(0), count(0), wakeup(false) + : QMutexData(mode), lastSpinCount(0), owner(0), count(0), wakeup(false) { report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init"); report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init"); diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp index 9d58953..a810000 100644 --- a/src/corelib/thread/qmutex_win.cpp +++ b/src/corelib/thread/qmutex_win.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode) - : recursive(mode == QMutex::Recursive), contenders(0), lastSpinCount(0), owner(0), count(0) + : QMutexData(mode), lastSpinCount(0), owner(0), count(0) { event = CreateEvent(0, FALSE, FALSE, 0); if (!event) diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h index 702125c..375ded1 100644 --- a/src/corelib/thread/qorderedmutexlocker_p.h +++ b/src/corelib/thread/qorderedmutexlocker_p.h @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE -class QMutex; +#include <QtCore/qmutex.h> /* Locks 2 mutexes in a defined order, avoiding a recursive lock if @@ -79,8 +79,8 @@ public: void relock() { if (!locked) { - if (mtx1) mtx1->lock(); - if (mtx2) mtx2->lock(); + if (mtx1) mtx1->lockInline(); + if (mtx2) mtx2->lockInline(); locked = true; } } @@ -88,8 +88,8 @@ public: void unlock() { if (locked) { - if (mtx1) mtx1->unlock(); - if (mtx2) mtx2->unlock(); + if (mtx1) mtx1->unlockInline(); + if (mtx2) mtx2->unlockInline(); locked = false; } } @@ -100,10 +100,10 @@ public: if (mtx1 == mtx2) return false; if (mtx1 < mtx2) { - mtx2->lock(); + mtx2->lockInline(); return true; } - if (!mtx2->tryLock()) { + if (!mtx2->tryLockInline()) { mtx1->unlock(); mtx2->lock(); mtx1->lock(); diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 722744c..99c9795 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -712,7 +712,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper() template <typename T> Q_OUTOFLINE_TEMPLATE QList<T>::~QList() { - if (d && !d->ref.deref()) + if (!d->ref.deref()) free(d); } @@ -740,8 +740,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::free(QListData::Data *data) { node_destruct(reinterpret_cast<Node *>(data->array + data->begin), reinterpret_cast<Node *>(data->array + data->end)); - if (data->ref == 0) - qFree(data); + qFree(data); } diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 6f4a20f..0b67a9c 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -1480,7 +1480,8 @@ QWidget::~QWidget() d->needsFlush = 0; // set all QPointers for this object to zero - QObjectPrivate::clearGuards(this); + if (d->hasGuards) + QObjectPrivate::clearGuards(this); if (d->declarativeData) { QAbstractDeclarativeData::destroyed(d->declarativeData, this); diff --git a/tests/benchmarks/corelib/thread/qmutex/qmutex.pro b/tests/benchmarks/corelib/thread/qmutex/qmutex.pro new file mode 100644 index 0000000..eda2f11 --- /dev/null +++ b/tests/benchmarks/corelib/thread/qmutex/qmutex.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_bench_qmutex + +SOURCES += tst_qmutex.cpp + diff --git a/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp b/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp new file mode 100644 index 0000000..fded508 --- /dev/null +++ b/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qtest.h> +#include <QtCore> + +#include <math.h> + +//TESTED_FILES= + + +class tst_QMutex : public QObject +{ + Q_OBJECT + +public: + tst_QMutex(); + virtual ~tst_QMutex(); + +private slots: + void noThread_data(); + void noThread(); +}; + +tst_QMutex::tst_QMutex() +{ +} + +tst_QMutex::~tst_QMutex() +{ +} + +void tst_QMutex::noThread_data() +{ + QTest::addColumn<int>("t"); + + QTest::newRow("noLock") << 1; + QTest::newRow("QMutexInline") << 2; + QTest::newRow("QMutex") << 3; + QTest::newRow("QMutexLocker") << 4; +} + +void tst_QMutex::noThread() +{ + volatile int count = 0; + const int N = 5000000; + QMutex mtx; + + QFETCH(int, t); + switch(t) { + case 1: + QBENCHMARK { + count = 0; + for (int i = 0; i < N; i++) { + count++; + } + } + break; + case 2: + QBENCHMARK { + count = 0; + for (int i = 0; i < N; i++) { + mtx.lockInline(); + count++; + mtx.unlockInline(); + } + } + break; + case 3: + QBENCHMARK { + count = 0; + for (int i = 0; i < N; i++) { + mtx.lock(); + count++; + mtx.unlock(); + } + } + break; + case 4: + QBENCHMARK { + count = 0; + for (int i = 0; i < N; i++) { + QMutexLocker locker(&mtx); + count++; + } + } + break; + } + QCOMPARE(int(count), N); +} + +QTEST_MAIN(tst_QMutex) +#include "tst_qmutex.moc" |