QThreadPool: Fix regression from Qt 4 in dealing with priority starts
The optimisation done in cbaf52b099
for Qt
5.0 got the order wrong of the comparison. The queue must be sorted in
decreasing priority order. But since higher numbers mean higher
priority, that means the queue must be sorted in decreasing priority
number order.
Task-number: QTBUG-29163
Change-Id: Iaf3424b9bb445bf5c71518927f37253cead454f3
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
This commit is contained in:
parent
0cad334ab6
commit
6c98035c99
@ -215,7 +215,7 @@ void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority)
|
||||
// put it on the queue
|
||||
QList<QPair<QRunnable *, int> >::const_iterator begin = queue.constBegin();
|
||||
QList<QPair<QRunnable *, int> >::const_iterator it = queue.constEnd();
|
||||
if (it != begin && priority < (*(it - 1)).second)
|
||||
if (it != begin && priority > (*(it - 1)).second)
|
||||
it = std::upper_bound(begin, --it, priority);
|
||||
queue.insert(it - begin, qMakePair(runnable, priority));
|
||||
runnableReady.wakeOne();
|
||||
|
@ -94,6 +94,8 @@ private slots:
|
||||
void tryStart();
|
||||
void tryStartPeakThreadCount();
|
||||
void tryStartCount();
|
||||
void priorityStart_data();
|
||||
void priorityStart();
|
||||
void waitForDone();
|
||||
void waitForDoneTimeout();
|
||||
void destroyingWaitsForTasksToFinish();
|
||||
@ -747,6 +749,57 @@ void tst_QThreadPool::tryStartCount()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QThreadPool::priorityStart_data()
|
||||
{
|
||||
QTest::addColumn<int>("otherCount");
|
||||
QTest::newRow("0") << 0;
|
||||
QTest::newRow("1") << 1;
|
||||
QTest::newRow("2") << 2;
|
||||
}
|
||||
|
||||
void tst_QThreadPool::priorityStart()
|
||||
{
|
||||
class Holder : public QRunnable
|
||||
{
|
||||
public:
|
||||
QSemaphore &sem;
|
||||
Holder(QSemaphore &sem) : sem(sem) {}
|
||||
void run()
|
||||
{
|
||||
sem.acquire();
|
||||
}
|
||||
};
|
||||
class Runner : public QRunnable
|
||||
{
|
||||
public:
|
||||
QAtomicPointer<QRunnable> &ptr;
|
||||
Runner(QAtomicPointer<QRunnable> &ptr) : ptr(ptr) {}
|
||||
void run()
|
||||
{
|
||||
ptr.testAndSetRelaxed(0, this);
|
||||
}
|
||||
};
|
||||
|
||||
QFETCH(int, otherCount);
|
||||
QSemaphore sem;
|
||||
QAtomicPointer<QRunnable> firstStarted;
|
||||
QRunnable *expected;
|
||||
QThreadPool threadPool;
|
||||
threadPool.setMaxThreadCount(1); // start only one thread at a time
|
||||
|
||||
// queue the holder first
|
||||
// We need to be sure that all threads are active when we
|
||||
// queue the two Runners
|
||||
threadPool.start(new Holder(sem));
|
||||
while (otherCount--)
|
||||
threadPool.start(new Runner(firstStarted), 0); // priority 0
|
||||
threadPool.start(expected = new Runner(firstStarted), 1); // priority 1
|
||||
|
||||
sem.release();
|
||||
QVERIFY(threadPool.waitForDone());
|
||||
QCOMPARE(firstStarted.load(), expected);
|
||||
}
|
||||
|
||||
void tst_QThreadPool::waitForDone()
|
||||
{
|
||||
QTime total, pass;
|
||||
|
Loading…
Reference in New Issue
Block a user