From aef03d80f7d9b71dfe777cd7927808d69dac0c27 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 23 Apr 2010 14:14:43 +0200 Subject: Optimize ~QList There is no need to check for d as it must never be 0 And the refcount ins QList::free() is nessecerly 0 since it is checked before the function is called Reviewed-by: ossi --- src/corelib/tools/qlist.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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::detach_helper() template Q_OUTOFLINE_TEMPLATE QList::~QList() { - if (d && !d->ref.deref()) + if (!d->ref.deref()) free(d); } @@ -740,8 +740,7 @@ Q_OUTOFLINE_TEMPLATE void QList::free(QListData::Data *data) { node_destruct(reinterpret_cast(data->array + data->begin), reinterpret_cast(data->array + data->end)); - if (data->ref == 0) - qFree(data); + qFree(data); } -- cgit v0.12 From c25a6e090c8074e68d7eb40f2533da8bab5e7dd8 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 21 Apr 2010 20:17:08 +0200 Subject: Inline the common case when there is no contention. QMutex locking could be used in performence critical code (such as QObject and co.) where the cost of a function call is not neglectible. This would slow down the common case where there is only one thread and no contention. Since we need to keep the old symbol for binary compatibilty, introduce new *Inline function. Reviewed-by: Brad --- src/corelib/kernel/qobject.cpp | 8 +- src/corelib/thread/qmutex.cpp | 133 ++++++++++++++++++++--------- src/corelib/thread/qmutex.h | 71 ++++++++++++--- src/corelib/thread/qmutex_p.h | 11 ++- src/corelib/thread/qmutex_unix.cpp | 2 +- src/corelib/thread/qmutex_win.cpp | 2 +- src/corelib/thread/qorderedmutexlocker_p.h | 14 +-- 7 files changed, 174 insertions(+), 67 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 8a4304e..f1262d6 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -893,7 +893,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 +917,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 +927,7 @@ QObject::~QObject() node = node->next; if (needToUnlock) - m->unlock(); + m->unlockInline(); } } @@ -2983,7 +2983,7 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, } if (needToUnlock) - receiverMutex->unlock(); + receiverMutex->unlockInline(); c->receiver = 0; 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(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(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(this->d); Qt::HANDLE self; if (d->recursive) { @@ -310,6 +276,7 @@ bool QMutex::tryLock() */ bool QMutex::tryLock(int timeout) { + QMutexPrivate *d = static_cast(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(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(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(d)->owner = 0; +#endif + static_cast(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 +#include #include 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(m) & quintptr(1u)) == quintptr(0), "QMutexLocker", "QMutex pointer is misaligned"); if (m) { - m->lock(); + m->lockInline(); val = reinterpret_cast(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 #include +#include 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 /* 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(); -- cgit v0.12 From 34a37c95a5130af262854eb7a7ef041908cc7aa8 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 22 Apr 2010 14:18:45 +0200 Subject: Benchmark for QMutex. This currently only cover the case when there is no contention $ ./tst_bench_qmutex noThread -callgrind ********* Start testing of tst_QMutex ********* Config: Using QTest library 4.7.0, Qt 4.7.0 PASS : tst_QMutex::initTestCase() RESULT : tst_QMutex::noThread():"noLock": 60,000,054 instruction reads per iteration (total: 60,000,054, iterations: 1) RESULT : tst_QMutex::noThread():"QMutexInline": 240,000,057 instruction reads per iteration (total: 240,000,057, iterations: 1) RESULT : tst_QMutex::noThread():"QMutex": 380,000,056 instruction reads per iteration (total: 380,000,056, iterations: 1) RESULT : tst_QMutex::noThread():"QMutexLocker": 240,000,058 instruction reads per iteration (total: 240,000,058, iterations: 1) PASS : tst_QMutex::noThread() PASS : tst_QMutex::cleanupTestCase() Totals: 3 passed, 0 failed, 0 skipped ********* Finished testing of tst_QMutex ********* $ make && ./tst_bench_qmutex noThread ********* Start testing of tst_QMutex ********* Config: Using QTest library 4.7.0, Qt 4.7.0 PASS : tst_QMutex::initTestCase() RESULT : tst_QMutex::noThread():"noLock": 27 msecs per iteration (total: 27, iterations: 1) RESULT : tst_QMutex::noThread():"QMutexInline": 212 msecs per iteration (total: 212, iterations: 1) RESULT : tst_QMutex::noThread():"QMutex": 257 msecs per iteration (total: 257, iterations: 1) RESULT : tst_QMutex::noThread():"QMutexLocker": 212 msecs per iteration (total: 212, iterations: 1) PASS : tst_QMutex::noThread() PASS : tst_QMutex::cleanupTestCase() Totals: 3 passed, 0 failed, 0 skipped ********* Finished testing of tst_QMutex ********* --- tests/benchmarks/corelib/thread/qmutex/qmutex.pro | 6 + .../corelib/thread/qmutex/tst_qmutex.cpp | 131 +++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 tests/benchmarks/corelib/thread/qmutex/qmutex.pro create mode 100644 tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp 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 +#include + +#include + +//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("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" -- cgit v0.12 From e25b5101981dfedd7ceab309b434d0cc15724a27 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 23 Apr 2010 11:43:30 +0200 Subject: Only emit the destroyed() signal if connected Also remove dead code in the exception code Reviewed-by: Brad --- src/corelib/kernel/qobject.cpp | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index f1262d6..0544a5a 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -840,22 +840,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) -- cgit v0.12 From 580d7f28ca93b053daa23250bdd404f0ddd7171e Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 23 Apr 2010 13:44:00 +0200 Subject: QObjectPrivate::deleteWatch, and inEventHandler are only used by jambi so #ifdef them out. Reviewed-by: Brad --- src/corelib/kernel/qobject.cpp | 17 ++++++++++++----- src/corelib/kernel/qobject.h | 2 +- src/corelib/kernel/qobject_p.h | 4 ++++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 0544a5a..ef1caef 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(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() @@ -1192,7 +1194,9 @@ bool QObject::event(QEvent *e) case QEvent::MetaCall: { +#ifdef QT_JAMBI_BUILD d_func()->inEventHandler = false; +#endif QMetaCallEvent *mce = static_cast(e); QObjectPrivate::Sender currentSender; currentSender.sender = const_cast(mce->sender()); @@ -1510,11 +1514,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(); 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 sharedRefcount; +#ifdef QT_JAMBI_BUILD int *deleteWatch; +#endif }; -- cgit v0.12 From cc10df56ba56899e993cb6e83a1fdfee79f60734 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 23 Apr 2010 14:00:49 +0200 Subject: Do not clear lists in ~QObject The list are going to be destroyed anyway Reviewed-by: Brad --- src/corelib/kernel/qobject.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index ef1caef..40add3f 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -933,12 +933,6 @@ QObject::~QObject() d->threadData->eventDispatcher->unregisterTimers(this); } -#ifdef QT3_SUPPORT - d->pendingChildInsertedEvents.clear(); -#endif - - d->eventFilters.clear(); - if (!d->children.isEmpty()) d->deleteChildren(); -- cgit v0.12 From 3f5aea3fa74f809a8ef2eb00c5c34233b7c5823b Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 23 Apr 2010 11:10:43 +0200 Subject: Test hasGuard before calling clearGuards. So no need to test it inside clearGuards. Reviewed-by: Brad --- src/corelib/kernel/qobject.cpp | 7 +------ src/gui/kernel/qwidget.cpp | 3 ++- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 40add3f..5dba965 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -478,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 { @@ -824,7 +819,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); 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); -- cgit v0.12 From 00ada3501d3b9fb9e40e217fef3ca0e9fb262e43 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 22 Apr 2010 17:20:54 +1000 Subject: Minor improvement to QObject constructor performance Reviewed-by: Olivier Goffart --- src/corelib/kernel/qobject.cpp | 52 +++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 5dba965..c01df66 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -729,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); } @@ -754,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 @@ -770,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); } -- cgit v0.12