summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/thread
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-02-16 21:46:20 +0100
committerLiang Qi <liang.qi@qt.io>2017-02-16 21:51:11 +0100
commitc577f6edafef7c40a5f78092ec4fcd78bb820b2c (patch)
tree9ca3819e5cca9b7e61f305a874b682e5a2085e83 /tests/auto/corelib/thread
parent99ce1d3d97c0423c3ee63ccf58deed964db0770e (diff)
parentde225ccdf95efb57866d62bc80872c1a2ab99703 (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.cpp6
-rw-r--r--tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp69
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()