tests: add ConcurrentQueueTest::waitAllFromMultipleThreads()

This new test hangs because ConcurrentQueue::nextJob() unblocks only
one of the threads that wait for _waitVar.
This commit is contained in:
Igor Kushnir 2021-03-12 17:30:46 +02:00 committed by Luis Ángel San Martín
parent 34b0698d02
commit 2cbcaaa391

View File

@ -155,9 +155,13 @@ public:
const auto format = messageFormatString().arg("%1 %2 %3"); const auto format = messageFormatString().arg("%1 %2 %3");
log() << format.arg("canceled").arg(canceledCount).arg(jobStr); log() << format.arg("canceled").arg(canceledCount).arg(jobStr);
} }
void printWaitedMessage() const void printBeginWaitingMessage() const
{ {
log() << threadMessageFormatString().arg("waited for"); log() << threadMessageFormatString().arg("begin waiting for");
}
void printEndWaitingMessage() const
{
log() << threadMessageFormatString().arg("end waiting for");
} }
private: private:
@ -187,8 +191,9 @@ std::size_t cancelAndPrint(ConcurrentQueue &queue, const QueueControlMessagePrin
void waitAndPrint(ConcurrentQueue &queue, const QueueControlMessagePrinter &printer) void waitAndPrint(ConcurrentQueue &queue, const QueueControlMessagePrinter &printer)
{ {
printer.printBeginWaitingMessage();
queue.waitAll(); queue.waitAll();
printer.printWaitedMessage(); printer.printEndWaitingMessage();
} }
} }
@ -211,6 +216,9 @@ private slots:
void cancelPending1UserThread_data(); void cancelPending1UserThread_data();
void cancelPending1UserThread(); void cancelPending1UserThread();
void waitAllFromMultipleThreads_data();
void waitAllFromMultipleThreads();
private: private:
static constexpr int primaryThreadId { 0 }; static constexpr int primaryThreadId { 0 };
@ -384,6 +392,44 @@ void ConcurrentQueueTest::cancelPending1UserThread()
QCOMPARE(total.load(), expectedTotal(jobs, canceledCount)); QCOMPARE(total.load(), expectedTotal(jobs, canceledCount));
} }
void ConcurrentQueueTest::waitAllFromMultipleThreads_data()
{
QTest::addColumn<int>("waitingThreadCount");
for (int i : { 1, 2, 4, 7, 19 })
QTest::addRow("%d", i) << i;
}
void ConcurrentQueueTest::waitAllFromMultipleThreads()
{
QFETCH(const int, waitingThreadCount);
QVERIFY(waitingThreadCount > 0);
constexpr auto queueThreadCount = 2;
const auto printer = makeMessagePrinter(queueThreadCount);
ConcurrentQueue queue(queueThreadCount);
printer.printStartedMessage();
using ms = chrono::milliseconds;
const JobDataSet jobs { { 5, ms(1) }, { 7, ms(2) } };
Enqueuer(queue, total, jobs, primaryThreadId)();
std::vector<std::thread> waitingThreads;
waitingThreads.reserve(waitingThreadCount - 1);
for (int id = 1; id < waitingThreadCount; ++id) {
waitingThreads.emplace_back([=, &queue] {
waitAndPrint(queue, QueueControlMessagePrinter(total, id, queueThreadCount));
});
}
waitAndPrint(queue, printer);
for (auto &t : waitingThreads)
t.join();
QCOMPARE(total.load(), expectedTotal(jobs));
}
QTEST_APPLESS_MAIN(ConcurrentQueueTest) QTEST_APPLESS_MAIN(ConcurrentQueueTest)
#include "concurrent_queue_test.moc" #include "concurrent_queue_test.moc"