TaskTree: Fix flakiness of DeeplyNestedParallelError test

It could happen that first process done was the one started
as 2nd one - in this case we should try to stop all the
processes potentially running, not only those starting
from index 1.

Simplify internal implementation.

Change-Id: I49049fba6bc4ef6a4544aaff5b582a976162edaf
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
Jarek Kobus
2023-01-27 16:28:04 +01:00
parent 1fbc707b3f
commit 825fea1fe9

View File

@@ -153,9 +153,8 @@ public:
bool isRunning() const { return m_doneCount >= 0; } bool isRunning() const { return m_doneCount >= 0; }
int currentLimit() const; int currentLimit() const;
TaskAction childDone(bool success); TaskAction childDone(bool success);
void groupDone(bool success); void groupDone();
void treeDone(bool success); void invokeEndHandler();
void invokeEndHandler(bool success);
void resetSuccessBit(); // only on start void resetSuccessBit(); // only on start
void updateSuccessBit(bool success); // only on childDone void updateSuccessBit(bool success); // only on childDone
@@ -350,8 +349,9 @@ TaskContainer::~TaskContainer()
TaskAction TaskContainer::start() TaskAction TaskContainer::start()
{ {
m_doneCount = 0; m_doneCount = 0;
resetSuccessBit();
createStorages(); createStorages();
TaskAction groupAction = m_children.isEmpty() ? TaskAction::StopWithDone : TaskAction::Continue; TaskAction groupAction = m_children.isEmpty() ? TaskAction::StopWithDone : TaskAction::Continue;
if (m_groupHandler.m_setupHandler) { if (m_groupHandler.m_setupHandler) {
StorageActivator activator(*this); StorageActivator activator(*this);
@@ -359,16 +359,17 @@ TaskAction TaskContainer::start()
groupAction = m_groupHandler.m_setupHandler(); groupAction = m_groupHandler.m_setupHandler();
} }
if (groupAction == TaskAction::StopWithDone || groupAction == TaskAction::StopWithError) { if (groupAction == TaskAction::Continue)
const bool success = groupAction == TaskAction::StopWithDone; groupAction = startChildren(0);
else
m_taskTreePrivate->advanceProgress(m_taskCount); m_taskTreePrivate->advanceProgress(m_taskCount);
invokeEndHandler(success);
groupDone(success); if (groupAction != TaskAction::Continue) {
return groupAction; updateSuccessBit(groupAction == TaskAction::StopWithDone);
groupDone();
} }
resetSuccessBit(); return groupAction;
return startChildren(0);
} }
TaskAction TaskContainer::startChildren(int nextChild) TaskAction TaskContainer::startChildren(int nextChild)
@@ -393,8 +394,6 @@ TaskAction TaskContainer::startChildren(int nextChild)
for (int j = i + 1; j < limit; ++j) for (int j = i + 1; j < limit; ++j)
skippedTaskCount += m_children.at(j)->taskCount(); skippedTaskCount += m_children.at(j)->taskCount();
m_taskTreePrivate->advanceProgress(skippedTaskCount); m_taskTreePrivate->advanceProgress(skippedTaskCount);
treeDone(finalizeAction == TaskAction::StopWithDone);
return finalizeAction; return finalizeAction;
} }
return TaskAction::Continue; return TaskAction::Continue;
@@ -408,7 +407,7 @@ void TaskContainer::stop()
const int childCount = m_children.size(); const int childCount = m_children.size();
const int limit = currentLimit(); const int limit = currentLimit();
for (int i = m_doneCount; i < limit; ++i) for (int i = 0; i < limit; ++i)
m_children.at(i)->stop(); m_children.at(i)->stop();
int skippedTaskCount = 0; int skippedTaskCount = 0;
@@ -432,55 +431,46 @@ TaskAction TaskContainer::childDone(bool success)
|| (m_workflowPolicy == WorkflowPolicy::StopOnError && !success); || (m_workflowPolicy == WorkflowPolicy::StopOnError && !success);
if (shouldStop) if (shouldStop)
stop(); stop();
else
++m_doneCount;
++m_doneCount;
updateSuccessBit(success); updateSuccessBit(success);
TaskAction groupAction = (shouldStop || m_doneCount == m_children.size())
? toTaskAction(m_successBit) : TaskAction::Continue;
if (isStarting())
return groupAction;
if (shouldStop || m_doneCount == m_children.size()) { if (groupAction == TaskAction::Continue) {
invokeEndHandler(m_successBit); groupAction = startChildren(limit);
groupDone(m_successBit); if (groupAction != TaskAction::Continue)
return toTaskAction(m_successBit); updateSuccessBit(groupAction == TaskAction::StopWithDone);
} }
if (m_parallelLimit == 0) if (groupAction != TaskAction::Continue)
return TaskAction::Continue; groupDone();
if (isStarting()) return groupAction;
return TaskAction::Continue;
if (limit >= m_children.size())
return TaskAction::Continue;
return startChildren(limit);
} }
void TaskContainer::groupDone(bool success) void TaskContainer::groupDone()
{ {
invokeEndHandler();
if (m_parentContainer) { if (m_parentContainer) {
if (!m_parentContainer->isStarting()) if (!m_parentContainer->isStarting())
m_parentContainer->childDone(success); m_parentContainer->childDone(m_successBit);
return; return;
} }
if (!isStarting()) if (m_successBit)
treeDone(success);
}
void TaskContainer::treeDone(bool success)
{
if (m_parentContainer)
return;
if (success)
m_taskTreePrivate->emitDone(); m_taskTreePrivate->emitDone();
else else
m_taskTreePrivate->emitError(); m_taskTreePrivate->emitError();
} }
void TaskContainer::invokeEndHandler(bool success) void TaskContainer::invokeEndHandler()
{ {
m_doneCount = -1; m_doneCount = -1;
m_successBit = success; const bool callDoneHandler = m_successBit && m_groupHandler.m_doneHandler;
const bool callDoneHandler = success && m_groupHandler.m_doneHandler; const bool callErrorHandler = !m_successBit && m_groupHandler.m_errorHandler;
const bool callErrorHandler = !success && m_groupHandler.m_errorHandler;
if (callDoneHandler || callErrorHandler) { if (callDoneHandler || callErrorHandler) {
StorageActivator activator(*this); StorageActivator activator(*this);
GuardLocker locker(m_taskTreePrivate->m_guard); GuardLocker locker(m_taskTreePrivate->m_guard);
@@ -611,7 +601,7 @@ void TaskNode::stop()
if (!m_task) { if (!m_task) {
m_container.stop(); m_container.stop();
m_container.invokeEndHandler(false); m_container.invokeEndHandler();
return; return;
} }