forked from qt-creator/qt-creator
TaskTree: Fix For loop with empty body
Ensure the For loop iterates even when the loop's body is empty. Simplify internals a bit. Change-Id: I4a269d61fa324a9c36109e95e74a992e915a72b0 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -2185,13 +2185,6 @@ SetupResult TaskTreePrivate::start(RuntimeContainer *container)
|
|||||||
container->m_successBit = startAction == SetupResult::StopWithSuccess;
|
container->m_successBit = startAction == SetupResult::StopWithSuccess;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (startAction == SetupResult::Continue
|
|
||||||
&& (containerNode.m_children.empty()
|
|
||||||
|| (containerNode.m_loop && !invokeLoopHandler(container)))) {
|
|
||||||
if (isProgressive(container))
|
|
||||||
advanceProgress(containerNode.m_taskCount);
|
|
||||||
startAction = toSetupResult(container->m_successBit);
|
|
||||||
}
|
|
||||||
return continueStart(container, startAction);
|
return continueStart(container, startAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2225,14 +2218,14 @@ SetupResult TaskTreePrivate::startChildren(RuntimeContainer *container)
|
|||||||
const int childCount = int(containerNode.m_children.size());
|
const int childCount = int(containerNode.m_children.size());
|
||||||
|
|
||||||
if (container->m_iterationCount == 0) {
|
if (container->m_iterationCount == 0) {
|
||||||
|
if (container->m_shouldIterate && !invokeLoopHandler(container)) {
|
||||||
|
if (isProgressive(container))
|
||||||
|
advanceProgress(containerNode.m_taskCount);
|
||||||
|
return toSetupResult(container->m_successBit);
|
||||||
|
}
|
||||||
container->m_iterations.emplace_back(
|
container->m_iterations.emplace_back(
|
||||||
std::make_unique<RuntimeIteration>(container->m_iterationCount, container));
|
std::make_unique<RuntimeIteration>(container->m_iterationCount, container));
|
||||||
++container->m_iterationCount;
|
++container->m_iterationCount;
|
||||||
} else if (containerNode.m_parallelLimit == 0) {
|
|
||||||
container->deleteFinishedIterations();
|
|
||||||
if (container->m_iterations.empty())
|
|
||||||
return toSetupResult(container->m_successBit);
|
|
||||||
return SetupResult::Continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GuardLocker locker(container->m_startGuard);
|
GuardLocker locker(container->m_startGuard);
|
||||||
@@ -2241,17 +2234,20 @@ SetupResult TaskTreePrivate::startChildren(RuntimeContainer *container)
|
|||||||
|| container->m_runningChildren < containerNode.m_parallelLimit) {
|
|| container->m_runningChildren < containerNode.m_parallelLimit) {
|
||||||
container->deleteFinishedIterations();
|
container->deleteFinishedIterations();
|
||||||
if (container->m_nextToStart == childCount) {
|
if (container->m_nextToStart == childCount) {
|
||||||
if (container->m_shouldIterate && invokeLoopHandler(container)) {
|
if (invokeLoopHandler(container)) {
|
||||||
container->m_nextToStart = 0;
|
container->m_nextToStart = 0;
|
||||||
container->m_iterations.emplace_back(
|
container->m_iterations.emplace_back(
|
||||||
std::make_unique<RuntimeIteration>(container->m_iterationCount, container));
|
std::make_unique<RuntimeIteration>(container->m_iterationCount, container));
|
||||||
++container->m_iterationCount;
|
++container->m_iterationCount;
|
||||||
|
} else if (container->m_iterations.empty()) {
|
||||||
|
return toSetupResult(container->m_successBit);
|
||||||
} else {
|
} else {
|
||||||
if (container->m_iterations.empty())
|
|
||||||
return toSetupResult(container->m_successBit);
|
|
||||||
return SetupResult::Continue;
|
return SetupResult::Continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (containerNode.m_children.size() == 0) // Empty loop body.
|
||||||
|
continue;
|
||||||
|
|
||||||
RuntimeIteration *iteration = container->m_iterations.back().get();
|
RuntimeIteration *iteration = container->m_iterations.back().get();
|
||||||
RuntimeTask *newTask = new RuntimeTask{containerNode.m_children.at(container->m_nextToStart),
|
RuntimeTask *newTask = new RuntimeTask{containerNode.m_children.at(container->m_nextToStart),
|
||||||
iteration};
|
iteration};
|
||||||
|
@@ -43,7 +43,8 @@ enum class Handler {
|
|||||||
Sync,
|
Sync,
|
||||||
BarrierAdvance,
|
BarrierAdvance,
|
||||||
Timeout,
|
Timeout,
|
||||||
Storage
|
Storage,
|
||||||
|
Iteration
|
||||||
};
|
};
|
||||||
Q_ENUM_NS(Handler);
|
Q_ENUM_NS(Handler);
|
||||||
|
|
||||||
@@ -2971,6 +2972,27 @@ void tst_Tasking::testTree_data()
|
|||||||
<< TestData{storage, root, {}, 1, DoneWith::Success, 0};
|
<< TestData{storage, root, {}, 1, DoneWith::Success, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Check if LoopUntil is executed with empty loop body.
|
||||||
|
const For root {
|
||||||
|
LoopUntil([storage](int iteration) {
|
||||||
|
storage->m_log.append({iteration, Handler::Iteration});
|
||||||
|
return iteration < 3;
|
||||||
|
}),
|
||||||
|
storage
|
||||||
|
};
|
||||||
|
|
||||||
|
const Log log {
|
||||||
|
{0, Handler::Iteration},
|
||||||
|
{1, Handler::Iteration},
|
||||||
|
{2, Handler::Iteration},
|
||||||
|
{3, Handler::Iteration} // The last iteration returns false
|
||||||
|
};
|
||||||
|
|
||||||
|
QTest::newRow("EmptyLoopUntil")
|
||||||
|
<< TestData{storage, root, log, 0, DoneWith::Success, 0};
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// Check if task tree finishes with the right progress value when onGroupSetup(false).
|
// Check if task tree finishes with the right progress value when onGroupSetup(false).
|
||||||
const Group root {
|
const Group root {
|
||||||
|
Reference in New Issue
Block a user