diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-12-24 04:26:34 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-12-24 04:26:34 (GMT) |
commit | 2c217b25e66aca9f39187b69bbe984b4e1445f87 (patch) | |
tree | 393bfff02954d7ae49ed68766ccfb2619ad87d88 /tests | |
parent | b270e0f4f3db56a4854782036cdb4ceacb7874ff (diff) | |
parent | 1c5a9b8d80b9dfe26b2d669e081d9a461c181222 (diff) | |
download | Qt-2c217b25e66aca9f39187b69bbe984b4e1445f87.zip Qt-2c217b25e66aca9f39187b69bbe984b4e1445f87.tar.gz Qt-2c217b25e66aca9f39187b69bbe984b4e1445f87.tar.bz2 |
Merge branch 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into master-integration
* 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1: (39 commits)
Whitespace change
Fix for coding conventions.
Fix resource leak in QCLuceneStandardAnalyzer::QCLuceneStandardAnalyzer.
Fix resource leak in QCLuceneStopAnalyzer::QCLuceneStopAnalyzer.
Assistant: Get rid of bogus warning.
add missing license header
Add inter-process binary shader cache for MeeGo
Track average wait times under our maximum spin time threshold
Store and track spin times in nanosecond resolution
Optimize adaptive spinning mutex code
Improve QMutex contention performance on Linux
Improve QMutex contention performance on Mac OS X
Disable spinning under lock contention on single CPU machines
Remove unnecessary testAndSetAcquire from QMutex::lockInternal()
Move contender count maintenance to QMutexPrivate
test contention when using 2 mutexes
Ensure that every thread does contend in the contention tests
Add baseline test data to measure test overhead
Test contention performance for long (10ms) critical sections
Add a benchmark for contended and uncontended QMutex performance
...
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/qcompleter/tst_qcompleter.cpp | 27 | ||||
-rw-r--r-- | tests/auto/qdatastream/tst_qdatastream.cpp | 51 | ||||
-rw-r--r-- | tests/auto/qelapsedtimer/tst_qelapsedtimer.cpp | 7 | ||||
-rw-r--r-- | tests/auto/qprogressbar/tst_qprogressbar.cpp | 7 | ||||
-rw-r--r-- | tests/auto/qtextstream/tst_qtextstream.cpp | 37 | ||||
-rw-r--r-- | tests/auto/qxmlstream/tst_qxmlstream.cpp | 82 | ||||
-rw-r--r-- | tests/benchmarks/corelib/thread/qmutex/qmutex.pro | 2 | ||||
-rw-r--r-- | tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp | 326 | ||||
-rw-r--r-- | tests/shared/filesystem.h | 3 |
9 files changed, 510 insertions, 32 deletions
diff --git a/tests/auto/qcompleter/tst_qcompleter.cpp b/tests/auto/qcompleter/tst_qcompleter.cpp index 650c328..62e64be 100644 --- a/tests/auto/qcompleter/tst_qcompleter.cpp +++ b/tests/auto/qcompleter/tst_qcompleter.cpp @@ -49,6 +49,7 @@ #include <QPointer> #include "../../shared/util.h" +#include "../../shared/filesystem.h" //TESTED_CLASS= //TESTED_FILES= @@ -1455,24 +1456,16 @@ void tst_QCompleter::task247560_keyboardNavigation() void tst_QCompleter::QTBUG_14292_filesystem() { - QDir tmpDir = QDir::temp(); + FileSystem fs; + QDir tmpDir = QDir::currentPath(); + qsrand(QTime::currentTime().msec()); QString d = "tst_QCompleter_" + QString::number(qrand()); - QVERIFY(tmpDir.mkdir(d)); - -#if 0 - struct Cleanup { - QString dir; - ~Cleanup() { - qDebug() << dir << - QFile::remove(dir); } - } cleanup; - cleanup.dir = tmpDir.absolutePath()+"/" +d; -#endif + QVERIFY(fs.createDirectory(tmpDir.filePath(d))); QVERIFY(tmpDir.cd(d)); - QVERIFY(tmpDir.mkdir("hello")); - QVERIFY(tmpDir.mkdir("holla")); + QVERIFY(fs.createDirectory(tmpDir.filePath("hello"))); + QVERIFY(fs.createDirectory(tmpDir.filePath("holla"))); QLineEdit edit; QCompleter comp; @@ -1500,12 +1493,12 @@ void tst_QCompleter::QTBUG_14292_filesystem() QCOMPARE(comp.popup()->model()->rowCount(), 1); QTest::keyClick(&edit, 'r'); QTRY_VERIFY(!comp.popup()->isVisible()); - QVERIFY(tmpDir.mkdir("hero")); + QVERIFY(fs.createDirectory(tmpDir.filePath("hero"))); QTRY_VERIFY(comp.popup()->isVisible()); QCOMPARE(comp.popup()->model()->rowCount(), 1); QTest::keyClick(comp.popup(), Qt::Key_Escape); QTRY_VERIFY(!comp.popup()->isVisible()); - QVERIFY(tmpDir.mkdir("nothingThere")); + QVERIFY(fs.createDirectory(tmpDir.filePath("nothingThere"))); //there is no reason creating a file should open a popup, it did in Qt 4.7.0 QTest::qWait(60); QVERIFY(!comp.popup()->isVisible()); @@ -1522,7 +1515,7 @@ void tst_QCompleter::QTBUG_14292_filesystem() QTest::qWaitForWindowShown(&w); QTRY_VERIFY(!edit.hasFocus() && !comp.popup()->hasFocus()); - QVERIFY(tmpDir.mkdir("hemo")); + QVERIFY(fs.createDirectory(tmpDir.filePath("hemo"))); //there is no reason creating a file should open a popup, it did in Qt 4.7.0 QTest::qWait(60); QVERIFY(!comp.popup()->isVisible()); diff --git a/tests/auto/qdatastream/tst_qdatastream.cpp b/tests/auto/qdatastream/tst_qdatastream.cpp index c03bc71..898fb84 100644 --- a/tests/auto/qdatastream/tst_qdatastream.cpp +++ b/tests/auto/qdatastream/tst_qdatastream.cpp @@ -168,6 +168,8 @@ private slots: void stream_atEnd_data(); void stream_atEnd(); + void stream_writeError(); + void stream_QByteArray2(); void setVersion_data(); @@ -2345,6 +2347,55 @@ void tst_QDataStream::stream_atEnd() } } +class FakeBuffer : public QBuffer +{ +protected: + qint64 writeData(const char *c, qint64 i) { return m_lock ? 0 : QBuffer::writeData(c, i); } +public: + FakeBuffer(bool locked = false) : m_lock(locked) {} + void setLocked(bool locked) { m_lock = locked; } +private: + bool m_lock; +}; + +#define TEST_WRITE_ERROR(op) \ + { \ + FakeBuffer fb(false); \ + QVERIFY(fb.open(QBuffer::ReadWrite)); \ + QDataStream fs(&fb); \ + fs.writeRawData("hello", 5); \ + /* first write some initial content */ \ + QCOMPARE(fs.status(), QDataStream::Ok); \ + QCOMPARE(fb.data(), QByteArray("hello")); \ + /* then test that writing can cause an error */ \ + fb.setLocked(true); \ + fs op; \ + QCOMPARE(fs.status(), QDataStream::WriteFailed); \ + QCOMPARE(fb.data(), QByteArray("hello")); \ + /* finally test that writing after an error doesn't change the stream any more */ \ + fb.setLocked(false); \ + fs op; \ + QCOMPARE(fs.status(), QDataStream::WriteFailed); \ + QCOMPARE(fb.data(), QByteArray("hello")); \ + } + +void tst_QDataStream::stream_writeError() +{ + TEST_WRITE_ERROR(<< true) + TEST_WRITE_ERROR(<< (qint8)1) + TEST_WRITE_ERROR(<< (quint8)1) + TEST_WRITE_ERROR(<< (qint16)1) + TEST_WRITE_ERROR(<< (quint16)1) + TEST_WRITE_ERROR(<< (qint32)1) + TEST_WRITE_ERROR(<< (quint32)1) + TEST_WRITE_ERROR(<< (qint64)1) + TEST_WRITE_ERROR(<< (quint64)1) + TEST_WRITE_ERROR(<< "hello") + TEST_WRITE_ERROR(<< (float)1.0) + TEST_WRITE_ERROR(<< (double)1.0) + TEST_WRITE_ERROR(.writeRawData("test", 4)) +} + void tst_QDataStream::stream_QByteArray2() { QByteArray ba; diff --git a/tests/auto/qelapsedtimer/tst_qelapsedtimer.cpp b/tests/auto/qelapsedtimer/tst_qelapsedtimer.cpp index 87df57d..bc61f52 100644 --- a/tests/auto/qelapsedtimer/tst_qelapsedtimer.cpp +++ b/tests/auto/qelapsedtimer/tst_qelapsedtimer.cpp @@ -122,11 +122,13 @@ void tst_QElapsedTimer::basics() quint64 value1 = t1.msecsSinceReference(); qDebug() << value1 << t1; + qint64 nsecs = t1.nsecsElapsed(); qint64 elapsed = t1.restart(); QVERIFY(elapsed < minResolution); + QVERIFY(nsecs / 1000000 < minResolution); quint64 value2 = t1.msecsSinceReference(); - qDebug() << value2 << t1 << elapsed; + qDebug() << value2 << t1 << elapsed << nsecs; // in theory, elapsed == value2 - value1 // However, since QElapsedTimer keeps internally the full resolution, @@ -150,7 +152,10 @@ void tst_QElapsedTimer::elapsed() // don't check: t1.secsTo(t2) // QVERIFY(t1 - t2 < 0); + QVERIFY(t1.nsecsElapsed() > 0); QVERIFY(t1.elapsed() > 0); + // the number of elapsed nanoseconds and milliseconds should match + QVERIFY(t1.nsecsElapsed() - t1.elapsed() * 1000000 < 1000000); QVERIFY(t1.hasExpired(minResolution)); QVERIFY(!t1.hasExpired(8*minResolution)); QVERIFY(!t2.hasExpired(minResolution)); diff --git a/tests/auto/qprogressbar/tst_qprogressbar.cpp b/tests/auto/qprogressbar/tst_qprogressbar.cpp index 7d94e3c..e042fb8 100644 --- a/tests/auto/qprogressbar/tst_qprogressbar.cpp +++ b/tests/auto/qprogressbar/tst_qprogressbar.cpp @@ -179,10 +179,15 @@ void tst_QProgressBar::format() bar.repainted = false; bar.setFormat("%v of %m (%p%)"); qApp->processEvents(); + #ifndef Q_WS_MAC - // The Mac scroll bar is animated, which means we get paint events all the time. + // Animated scroll bars get paint events all the time +#ifdef Q_OS_WIN + if (QSysInfo::WindowsVersion < QSysInfo::WV_VISTA) +#endif QVERIFY(!bar.repainted); #endif + QCOMPARE(bar.text(), QString("1 of 10 (10%)")); bar.setRange(5, 5); bar.setValue(5); diff --git a/tests/auto/qtextstream/tst_qtextstream.cpp b/tests/auto/qtextstream/tst_qtextstream.cpp index 4c78ef0..005f686 100644 --- a/tests/auto/qtextstream/tst_qtextstream.cpp +++ b/tests/auto/qtextstream/tst_qtextstream.cpp @@ -228,6 +228,7 @@ private slots: void status_real_read(); void status_integer_read(); void status_word_read(); + void status_write_error(); // use case tests void useCase1(); @@ -4176,6 +4177,42 @@ void tst_QTextStream::status_word_read() QCOMPARE(s.status(), QTextStream::ReadPastEnd); } +class FakeBuffer : public QBuffer +{ +protected: + qint64 writeData(const char *c, qint64 i) { return m_lock ? 0 : QBuffer::writeData(c, i); } +public: + FakeBuffer(bool locked = false) : m_lock(locked) {} + void setLocked(bool locked) { m_lock = locked; } +private: + bool m_lock; +}; + +void tst_QTextStream::status_write_error() +{ + FakeBuffer fb(false); + QVERIFY(fb.open(QBuffer::ReadWrite)); + QTextStream fs(&fb); + fs.setCodec(QTextCodec::codecForName("latin1")); + /* first write some initial content */ + fs << "hello"; + fs.flush(); + QCOMPARE(fs.status(), QTextStream::Ok); + QCOMPARE(fb.data(), QByteArray("hello")); + /* then test that writing can cause an error */ + fb.setLocked(true); + fs << "error"; + fs.flush(); + QCOMPARE(fs.status(), QTextStream::WriteFailed); + QCOMPARE(fb.data(), QByteArray("hello")); + /* finally test that writing after an error doesn't change the stream any more */ + fb.setLocked(false); + fs << "can't do that"; + fs.flush(); + QCOMPARE(fs.status(), QTextStream::WriteFailed); + QCOMPARE(fb.data(), QByteArray("hello")); +} + void tst_QTextStream::task180679_alignAccountingStyle() { { diff --git a/tests/auto/qxmlstream/tst_qxmlstream.cpp b/tests/auto/qxmlstream/tst_qxmlstream.cpp index 19e4b90..9e4f3ec 100644 --- a/tests/auto/qxmlstream/tst_qxmlstream.cpp +++ b/tests/auto/qxmlstream/tst_qxmlstream.cpp @@ -574,6 +574,7 @@ private slots: void checkCommentIndentation() const; void checkCommentIndentation_data() const; void qtbug9196_crash() const; + void hasError() const; private: static QByteArray readFile(const QString &filename); @@ -1560,5 +1561,86 @@ void tst_QXmlStream::qtbug9196_crash() const } } +class FakeBuffer : public QBuffer +{ +protected: + qint64 writeData(const char *c, qint64 i) + { + qint64 ai = qMin(m_capacity, i); + m_capacity -= ai; + return ai ? QBuffer::writeData(c, ai) : 0; + } +public: + void setCapacity(int capacity) { m_capacity = capacity; } +private: + qint64 m_capacity; +}; + +void tst_QXmlStream::hasError() const +{ + { + FakeBuffer fb; + QVERIFY(fb.open(QBuffer::ReadWrite)); + fb.setCapacity(1000); + QXmlStreamWriter writer(&fb); + writer.writeStartDocument(); + writer.writeEndDocument(); + QVERIFY(!writer.hasError()); + QCOMPARE(fb.data(), QByteArray("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")); + } + + { + // Failure caused by write(QString) + FakeBuffer fb; + QVERIFY(fb.open(QBuffer::ReadWrite)); + fb.setCapacity(strlen("<?xml version=\"")); + QXmlStreamWriter writer(&fb); + writer.writeStartDocument(); + QVERIFY(writer.hasError()); + QCOMPARE(fb.data(), QByteArray("<?xml version=\"")); + } + + { + // Failure caused by write(char *) + FakeBuffer fb; + QVERIFY(fb.open(QBuffer::ReadWrite)); + fb.setCapacity(strlen("<?xml version=\"1.0")); + QXmlStreamWriter writer(&fb); + writer.writeStartDocument(); + QVERIFY(writer.hasError()); + QCOMPARE(fb.data(), QByteArray("<?xml version=\"1.0")); + } + + { + // Failure caused by write(QStringRef) + FakeBuffer fb; + QVERIFY(fb.open(QBuffer::ReadWrite)); + fb.setCapacity(strlen("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test xmlns:")); + QXmlStreamWriter writer(&fb); + writer.writeStartDocument(); + writer.writeStartElement("test"); + writer.writeNamespace("http://foo.bar", "foo"); + QVERIFY(writer.hasError()); + QCOMPARE(fb.data(), QByteArray("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test xmlns:")); + } + + { + // Refusal to write after 1st failure + FakeBuffer fb; + QVERIFY(fb.open(QBuffer::ReadWrite)); + fb.setCapacity(10); + QXmlStreamWriter writer(&fb); + writer.writeStartDocument(); + QVERIFY(writer.hasError()); + QCOMPARE(fb.data(), QByteArray("<?xml vers")); + fb.setCapacity(1000); + writer.writeStartElement("test"); // literal & qstring + writer.writeNamespace("http://foo.bar", "foo"); // literal & qstringref + QVERIFY(writer.hasError()); + QCOMPARE(fb.data(), QByteArray("<?xml vers")); + } + +} + #include "tst_qxmlstream.moc" // vim: et:ts=4:sw=4:sts=4 diff --git a/tests/benchmarks/corelib/thread/qmutex/qmutex.pro b/tests/benchmarks/corelib/thread/qmutex/qmutex.pro index eda2f11..8fda5fa 100644 --- a/tests/benchmarks/corelib/thread/qmutex/qmutex.pro +++ b/tests/benchmarks/corelib/thread/qmutex/qmutex.pro @@ -1,6 +1,6 @@ load(qttest_p4) TEMPLATE = app TARGET = tst_bench_qmutex - +QT -= gui SOURCES += tst_qmutex.cpp diff --git a/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp b/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp index fded508..b0c5702 100644 --- a/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp +++ b/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp @@ -39,34 +39,93 @@ ** ****************************************************************************/ -#include <qtest.h> -#include <QtCore> +#include <QtCore/QtCore> +#include <QtTest/QtTest> #include <math.h> -//TESTED_FILES= +#ifdef Q_OS_UNIX +# include <pthread.h> +# include <errno.h> +typedef pthread_mutex_t NativeMutexType; +void NativeMutexInitialize(NativeMutexType *mutex) +{ + pthread_mutex_init(mutex, NULL); +} +void NativeMutexDestroy(NativeMutexType *mutex) +{ + pthread_mutex_destroy(mutex); +} +void NativeMutexLock(NativeMutexType *mutex) +{ + pthread_mutex_lock(mutex); +} +void NativeMutexUnlock(NativeMutexType *mutex) +{ + pthread_mutex_unlock(mutex); +} +#elif defined(Q_OS_WIN) +# define _WIN32_WINNT 0x0400 +# include <windows.h> +typedef CRITICAL_SECTION NativeMutexType; +void NativeMutexInitialize(NativeMutexType *mutex) +{ + InitializeCriticalSection(mutex); +} +void NativeMutexDestroy(NativeMutexType *mutex) +{ + DeleteCriticalSection(mutex); +} +void NativeMutexLock(NativeMutexType *mutex) +{ + EnterCriticalSection(mutex); +} +void NativeMutexUnlock(NativeMutexType *mutex) +{ + LeaveCriticalSection(mutex); +} +#endif +//TESTED_FILES= class tst_QMutex : public QObject { Q_OBJECT + int threadCount; + public: - tst_QMutex(); - virtual ~tst_QMutex(); + // barriers for the contended tests + static QSemaphore semaphore1, semaphore2, semaphore3, semaphore4; + + tst_QMutex() + { + // at least 2 threads, even on single cpu/core machines + threadCount = qMax(2, QThread::idealThreadCount()); + qDebug("thread count: %d", threadCount); + } private slots: void noThread_data(); void noThread(); -}; -tst_QMutex::tst_QMutex() -{ -} + void uncontendedNative(); + void uncontendedQMutex(); + void uncontendedQMutexLocker(); -tst_QMutex::~tst_QMutex() -{ -} + void contendedNative_data(); + void contendedQMutex_data() { contendedNative_data(); } + void contendedQMutexLocker_data() { contendedNative_data(); } + + void contendedNative(); + void contendedQMutex(); + void contendedQMutexLocker(); +}; + +QSemaphore tst_QMutex::semaphore1; +QSemaphore tst_QMutex::semaphore2; +QSemaphore tst_QMutex::semaphore3; +QSemaphore tst_QMutex::semaphore4; void tst_QMutex::noThread_data() { @@ -127,5 +186,248 @@ void tst_QMutex::noThread() QCOMPARE(int(count), N); } +void tst_QMutex::uncontendedNative() +{ + NativeMutexType mutex; + NativeMutexInitialize(&mutex); + QBENCHMARK { + NativeMutexLock(&mutex); + NativeMutexUnlock(&mutex); + } + NativeMutexDestroy(&mutex); +} + +void tst_QMutex::uncontendedQMutex() +{ + QMutex mutex; + QBENCHMARK { + mutex.lock(); + mutex.unlock(); + } +} + +void tst_QMutex::uncontendedQMutexLocker() +{ + QMutex mutex; + QBENCHMARK { + QMutexLocker locker(&mutex); + } +} + +void tst_QMutex::contendedNative_data() +{ + QTest::addColumn<int>("iterations"); + QTest::addColumn<int>("msleepDuration"); + QTest::addColumn<bool>("use2mutexes"); + + QTest::newRow("baseline") << 0 << -1 << false; + + QTest::newRow("no msleep, 1 mutex") << 1000 << -1 << false; + QTest::newRow("no msleep, 2 mutexes") << 1000 << -1 << true; + QTest::newRow("msleep(0), 1 mutex") << 1000 << 0 << false; + QTest::newRow("msleep(0), 2 mutexes") << 1000 << 0 << true; + QTest::newRow("msleep(1), 1 mutex") << 10 << 1 << false; + QTest::newRow("msleep(1), 2 mutexes") << 10 << 1 << true; + QTest::newRow("msleep(2), 1 mutex") << 10 << 2 << false; + QTest::newRow("msleep(2), 2 mutexes") << 10 << 2 << true; + QTest::newRow("msleep(10), 1 mutex") << 10 << 10 << false; + QTest::newRow("msleep(10), 2 mutexes") << 10 << 10 << true; +} + +class NativeMutexThread : public QThread +{ + NativeMutexType *mutex1, *mutex2; + int iterations, msleepDuration; + bool use2mutexes; +public: + bool done; + NativeMutexThread(NativeMutexType *mutex1, NativeMutexType *mutex2, int iterations, int msleepDuration, bool use2mutexes) + : mutex1(mutex1), mutex2(mutex2), iterations(iterations), msleepDuration(msleepDuration), use2mutexes(use2mutexes), done(false) + { } + void run() { + forever { + tst_QMutex::semaphore1.release(); + tst_QMutex::semaphore2.acquire(); + if (done) + break; + for (int i = 0; i < iterations; ++i) { + NativeMutexLock(mutex1); + if (use2mutexes) + NativeMutexLock(mutex2); + if (msleepDuration >= 0) + msleep(msleepDuration); + if (use2mutexes) + NativeMutexUnlock(mutex2); + NativeMutexUnlock(mutex1); + + QThread::yieldCurrentThread(); + } + tst_QMutex::semaphore3.release(); + tst_QMutex::semaphore4.acquire(); + } + } +}; + +void tst_QMutex::contendedNative() +{ + QFETCH(int, iterations); + QFETCH(int, msleepDuration); + QFETCH(bool, use2mutexes); + + NativeMutexType mutex1, mutex2; + NativeMutexInitialize(&mutex1); + NativeMutexInitialize(&mutex2); + + QVector<NativeMutexThread *> threads(threadCount); + for (int i = 0; i < threads.count(); ++i) { + threads[i] = new NativeMutexThread(&mutex1, &mutex2, iterations, msleepDuration, use2mutexes); + threads[i]->start(); + } + + QBENCHMARK { + semaphore1.acquire(threadCount); + semaphore2.release(threadCount); + semaphore3.acquire(threadCount); + semaphore4.release(threadCount); + } + + for (int i = 0; i < threads.count(); ++i) + threads[i]->done = true; + semaphore1.acquire(threadCount); + semaphore2.release(threadCount); + for (int i = 0; i < threads.count(); ++i) + threads[i]->wait(); + qDeleteAll(threads); + + NativeMutexDestroy(&mutex1); + NativeMutexDestroy(&mutex2); +} + +class QMutexThread : public QThread +{ + QMutex *mutex1, *mutex2; + int iterations, msleepDuration; + bool use2mutexes; +public: + bool done; + QMutexThread(QMutex *mutex1, QMutex *mutex2, int iterations, int msleepDuration, bool use2mutexes) + : mutex1(mutex1), mutex2(mutex2), iterations(iterations), msleepDuration(msleepDuration), use2mutexes(use2mutexes), done(false) + { } + void run() { + forever { + tst_QMutex::semaphore1.release(); + tst_QMutex::semaphore2.acquire(); + if (done) + break; + for (int i = 0; i < iterations; ++i) { + mutex1->lock(); + if (use2mutexes) + mutex2->lock(); + if (msleepDuration >= 0) + msleep(msleepDuration); + if (use2mutexes) + mutex2->unlock(); + mutex1->unlock(); + + QThread::yieldCurrentThread(); + } + tst_QMutex::semaphore3.release(); + tst_QMutex::semaphore4.acquire(); + } + } +}; + +void tst_QMutex::contendedQMutex() +{ + QFETCH(int, iterations); + QFETCH(int, msleepDuration); + QFETCH(bool, use2mutexes); + + QMutex mutex1, mutex2; + + QVector<QMutexThread *> threads(threadCount); + for (int i = 0; i < threads.count(); ++i) { + threads[i] = new QMutexThread(&mutex1, &mutex2, iterations, msleepDuration, use2mutexes); + threads[i]->start(); + } + + QBENCHMARK { + semaphore1.acquire(threadCount); + semaphore2.release(threadCount); + semaphore3.acquire(threadCount); + semaphore4.release(threadCount); + } + + for (int i = 0; i < threads.count(); ++i) + threads[i]->done = true; + semaphore1.acquire(threadCount); + semaphore2.release(threadCount); + for (int i = 0; i < threads.count(); ++i) + threads[i]->wait(); + qDeleteAll(threads); +} + +class QMutexLockerThread : public QThread +{ + QMutex *mutex1, *mutex2; + int iterations, msleepDuration; + bool use2mutexes; +public: + bool done; + QMutexLockerThread(QMutex *mutex1, QMutex *mutex2, int iterations, int msleepDuration, bool use2mutexes) + : mutex1(mutex1), mutex2(mutex2), iterations(iterations), msleepDuration(msleepDuration), use2mutexes(use2mutexes), done(false) + { } + void run() { + forever { + tst_QMutex::semaphore1.release(); + tst_QMutex::semaphore2.acquire(); + if (done) + break; + for (int i = 0; i < iterations; ++i) { + { + QMutexLocker locker1(mutex1); + QMutexLocker locker2(use2mutexes ? mutex2 : 0); + if (msleepDuration >= 0) + msleep(msleepDuration); + } + + QThread::yieldCurrentThread(); + } + tst_QMutex::semaphore3.release(); + tst_QMutex::semaphore4.acquire(); + } + } +}; + +void tst_QMutex::contendedQMutexLocker() +{ + QFETCH(int, iterations); + QFETCH(int, msleepDuration); + QFETCH(bool, use2mutexes); + + QMutex mutex1, mutex2; + + QVector<QMutexLockerThread *> threads(threadCount); + for (int i = 0; i < threads.count(); ++i) { + threads[i] = new QMutexLockerThread(&mutex1, &mutex2, iterations, msleepDuration, use2mutexes); + threads[i]->start(); + } + + QBENCHMARK { + semaphore1.acquire(threadCount); + semaphore2.release(threadCount); + semaphore3.acquire(threadCount); + semaphore4.release(threadCount); + } + + for (int i = 0; i < threads.count(); ++i) + threads[i]->done = true; + semaphore1.acquire(threadCount); + semaphore2.release(threadCount); + for (int i = 0; i < threads.count(); ++i) + threads[i]->wait(); + qDeleteAll(threads); +} + QTEST_MAIN(tst_QMutex) #include "tst_qmutex.moc" diff --git a/tests/shared/filesystem.h b/tests/shared/filesystem.h index 8274346..4775671 100644 --- a/tests/shared/filesystem.h +++ b/tests/shared/filesystem.h @@ -55,6 +55,9 @@ #define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) #endif #define REPARSE_MOUNTPOINT_HEADER_SIZE 8 +#ifndef FSCTL_SET_REPARSE_POINT +#define FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) +#endif #endif struct FileSystem |