summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/thread
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-02-17 20:10:34 +0100
committerLiang Qi <liang.qi@qt.io>2017-02-17 20:10:34 +0100
commitbc4cd465dd5df82e13f3c7709166ee11289d219f (patch)
treed6323aaed6383e589fbefb6057648c22bb187c76 /tests/auto/corelib/thread
parent43daefb0962794b2df256cae1098e889b9b36f12 (diff)
parent07745d7bfbf6c8d83e0243150d8ce934675dea87 (diff)
Merge remote-tracking branch 'origin/5.9' into dev
Conflicts: qmake/Makefile.unix Change-Id: Ia18e391198222eef34ffa2df6f683e052058d032
Diffstat (limited to 'tests/auto/corelib/thread')
-rw-r--r--tests/auto/corelib/thread/qsemaphore/BLACKLIST2
-rw-r--r--tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp6
-rw-r--r--tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp69
-rw-r--r--tests/auto/corelib/thread/qwaitcondition/BLACKLIST2
4 files changed, 61 insertions, 18 deletions
diff --git a/tests/auto/corelib/thread/qsemaphore/BLACKLIST b/tests/auto/corelib/thread/qsemaphore/BLACKLIST
new file mode 100644
index 0000000000..22e30d0fd6
--- /dev/null
+++ b/tests/auto/corelib/thread/qsemaphore/BLACKLIST
@@ -0,0 +1,2 @@
+[tryAcquireWithTimeout:0.2s]
+windows
diff --git a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
index a33417c7da..ba470a77c9 100644
--- a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
+++ b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
@@ -368,16 +368,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()
diff --git a/tests/auto/corelib/thread/qwaitcondition/BLACKLIST b/tests/auto/corelib/thread/qwaitcondition/BLACKLIST
new file mode 100644
index 0000000000..3ff336576b
--- /dev/null
+++ b/tests/auto/corelib/thread/qwaitcondition/BLACKLIST
@@ -0,0 +1,2 @@
+[wakeOne]
+windows