diff options
author | Liang Qi <liang.qi@qt.io> | 2017-02-16 21:46:20 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2017-02-16 21:51:11 +0100 |
commit | c577f6edafef7c40a5f78092ec4fcd78bb820b2c (patch) | |
tree | 9ca3819e5cca9b7e61f305a874b682e5a2085e83 /tests/auto/corelib/thread | |
parent | 99ce1d3d97c0423c3ee63ccf58deed964db0770e (diff) | |
parent | de225ccdf95efb57866d62bc80872c1a2ab99703 (diff) |
Merge remote-tracking branch 'origin/5.8' into 5.9
Conflicts:
src/corelib/plugin/qlibrary_unix.cpp
src/plugins/platforms/xcb/qxcbconnection.cpp
tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
Change-Id: I632c400d909f8c204f55743aadc7886af2f15dfb
Diffstat (limited to 'tests/auto/corelib/thread')
-rw-r--r-- | tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp | 6 | ||||
-rw-r--r-- | tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp | 69 |
2 files changed, 57 insertions, 18 deletions
diff --git a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp index f1eb32a282..2970b2e118 100644 --- a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp +++ b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp @@ -367,16 +367,18 @@ public: void run(); }; +static const int Timeout = 60 * 1000; // 1min + void Producer::run() { for (int i = 0; i < DataSize; ++i) { - freeSpace.acquire(); + QVERIFY(freeSpace.tryAcquire(1, Timeout)); buffer[i % BufferSize] = alphabet[i % AlphabetSize]; usedSpace.release(); } for (int i = 0; i < DataSize; ++i) { if ((i % ProducerChunkSize) == 0) - freeSpace.acquire(ProducerChunkSize); + QVERIFY(freeSpace.tryAcquire(ProducerChunkSize, Timeout)); buffer[i % BufferSize] = alphabet[i % AlphabetSize]; if ((i % ProducerChunkSize) == (ProducerChunkSize - 1)) usedSpace.release(ProducerChunkSize); diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp index 3bc3f8a759..5b7242fddb 100644 --- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -958,51 +958,88 @@ void tst_QThreadPool::clear() void tst_QThreadPool::cancel() { QSemaphore sem(0); + QSemaphore startedThreads(0); + + class SemaphoreReleaser + { + QSemaphore &sem; + int n; + Q_DISABLE_COPY(SemaphoreReleaser) + public: + explicit SemaphoreReleaser(QSemaphore &sem, int n) + : sem(sem), n(n) {} + + ~SemaphoreReleaser() + { + sem.release(n); + } + }; + class BlockingRunnable : public QRunnable { public: QSemaphore & sem; - int & dtorCounter; - int & runCounter; + QSemaphore &startedThreads; + QAtomicInt &dtorCounter; + QAtomicInt &runCounter; int dummy; - BlockingRunnable(QSemaphore & s, int & c, int & r) : sem(s), dtorCounter(c), runCounter(r){} - ~BlockingRunnable(){dtorCounter++;} + + explicit BlockingRunnable(QSemaphore &s, QSemaphore &started, QAtomicInt &c, QAtomicInt &r) + : sem(s), startedThreads(started), dtorCounter(c), runCounter(r){} + + ~BlockingRunnable() + { + dtorCounter.fetchAndAddRelaxed(1); + } + void run() { - runCounter++; + startedThreads.release(); + runCounter.fetchAndAddRelaxed(1); sem.acquire(); count.ref(); } }; - typedef BlockingRunnable* BlockingRunnablePtr; + + enum { + MaxThreadCount = 3, + OverProvisioning = 2, + runs = MaxThreadCount * OverProvisioning + }; QThreadPool threadPool; - threadPool.setMaxThreadCount(3); - int runs = 2 * threadPool.maxThreadCount(); - BlockingRunnablePtr* runnables = new BlockingRunnablePtr[runs]; + threadPool.setMaxThreadCount(MaxThreadCount); + BlockingRunnable *runnables[runs]; + + // ensure that the QThreadPool doesn't deadlock if any of the checks fail + // and cause an early return: + const SemaphoreReleaser semReleaser(sem, runs); + count.store(0); - int dtorCounter = 0; - int runCounter = 0; + QAtomicInt dtorCounter = 0; + QAtomicInt runCounter = 0; for (int i = 0; i < runs; i++) { - runnables[i] = new BlockingRunnable(sem, dtorCounter, runCounter); + runnables[i] = new BlockingRunnable(sem, startedThreads, dtorCounter, runCounter); runnables[i]->setAutoDelete(i != 0 && i != (runs-1)); //one which will run and one which will not threadPool.cancel(runnables[i]); //verify NOOP for jobs not in the queue threadPool.start(runnables[i]); } + // wait for all worker threads to have started up: + QVERIFY(startedThreads.tryAcquire(MaxThreadCount, 60*1000 /* 1min */)); + for (int i = 0; i < runs; i++) { threadPool.cancel(runnables[i]); } runnables[0]->dummy = 0; //valgrind will catch this if cancel() is crazy enough to delete currently running jobs runnables[runs-1]->dummy = 0; - QCOMPARE(dtorCounter, runs-threadPool.maxThreadCount()-1); + QCOMPARE(dtorCounter.load(), runs - threadPool.maxThreadCount() - 1); sem.release(threadPool.maxThreadCount()); threadPool.waitForDone(); - QCOMPARE(runCounter, threadPool.maxThreadCount()); + QCOMPARE(runCounter.load(), threadPool.maxThreadCount()); QCOMPARE(count.load(), threadPool.maxThreadCount()); - QCOMPARE(dtorCounter, runs-2); + QCOMPARE(dtorCounter.load(), runs - 2); delete runnables[0]; //if the pool deletes them then we'll get double-free crash delete runnables[runs-1]; - delete[] runnables; } void tst_QThreadPool::destroyingWaitsForTasksToFinish() |