forked from qt-creator/qt-creator
TaskTree: Prepare infrastructure for iterators
Task-number: QTCREATORBUG-30081 Change-Id: I5ad78314445508f52c3fb2ab0fd696940fe7b6dd Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -1345,12 +1345,14 @@ GroupItem GroupItem::withTimeout(const GroupItem &item, milliseconds timeout,
|
|||||||
|
|
||||||
class TaskTreePrivate;
|
class TaskTreePrivate;
|
||||||
class TaskNode;
|
class TaskNode;
|
||||||
class RuntimeTask;
|
|
||||||
class RuntimeContainer;
|
class RuntimeContainer;
|
||||||
|
class RuntimeIteration;
|
||||||
|
class RuntimeTask;
|
||||||
|
|
||||||
class ExecutionContextActivator
|
class ExecutionContextActivator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ExecutionContextActivator(RuntimeIteration *iteration) { activateContext(iteration); }
|
||||||
ExecutionContextActivator(RuntimeContainer *container) { activateContext(container); }
|
ExecutionContextActivator(RuntimeContainer *container) { activateContext(container); }
|
||||||
~ExecutionContextActivator() {
|
~ExecutionContextActivator() {
|
||||||
for (int i = m_activeStorages.size() - 1; i >= 0; --i) // iterate in reverse order
|
for (int i = m_activeStorages.size() - 1; i >= 0; --i) // iterate in reverse order
|
||||||
@@ -1358,6 +1360,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void activateContext(RuntimeIteration *iteration);
|
||||||
void activateContext(RuntimeContainer *container);
|
void activateContext(RuntimeContainer *container);
|
||||||
QList<StorageBase> m_activeStorages;
|
QList<StorageBase> m_activeStorages;
|
||||||
};
|
};
|
||||||
@@ -1448,13 +1451,13 @@ public:
|
|||||||
SetupResult start(RuntimeContainer *container);
|
SetupResult start(RuntimeContainer *container);
|
||||||
SetupResult continueStart(RuntimeContainer *container, SetupResult startAction);
|
SetupResult continueStart(RuntimeContainer *container, SetupResult startAction);
|
||||||
SetupResult startChildren(RuntimeContainer *container);
|
SetupResult startChildren(RuntimeContainer *container);
|
||||||
SetupResult childDone(RuntimeContainer *container, bool success);
|
SetupResult childDone(RuntimeIteration *iteration, bool success);
|
||||||
void stop(RuntimeContainer *container);
|
void stop(RuntimeContainer *container);
|
||||||
bool invokeDoneHandler(RuntimeContainer *container, DoneWith doneWith);
|
bool invokeDoneHandler(RuntimeContainer *container, DoneWith doneWith);
|
||||||
|
|
||||||
template <typename Handler, typename ...Args,
|
template <typename Container, typename Handler, typename ...Args,
|
||||||
typename ReturnType = std::invoke_result_t<Handler, Args...>>
|
typename ReturnType = std::invoke_result_t<Handler, Args...>>
|
||||||
ReturnType invokeHandler(RuntimeContainer *container, Handler &&handler, Args &&...args)
|
ReturnType invokeHandler(Container *container, Handler &&handler, Args &&...args)
|
||||||
{
|
{
|
||||||
ExecutionContextActivator activator(container);
|
ExecutionContextActivator activator(container);
|
||||||
GuardLocker locker(m_guard);
|
GuardLocker locker(m_guard);
|
||||||
@@ -1487,6 +1490,21 @@ static bool initialSuccessBit(WorkflowPolicy workflowPolicy)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RuntimeIteration
|
||||||
|
{
|
||||||
|
Q_DISABLE_COPY(RuntimeIteration)
|
||||||
|
|
||||||
|
public:
|
||||||
|
int continueIndex() const;
|
||||||
|
int currentLimit() const;
|
||||||
|
void deleteChild(RuntimeTask *node);
|
||||||
|
|
||||||
|
const int m_iterationIndex = 0;
|
||||||
|
RuntimeContainer *m_container = nullptr;
|
||||||
|
std::vector<std::unique_ptr<RuntimeTask>> m_children = {}; // Owning.
|
||||||
|
int m_doneCount = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class RuntimeContainer
|
class RuntimeContainer
|
||||||
{
|
{
|
||||||
Q_DISABLE_COPY(RuntimeContainer)
|
Q_DISABLE_COPY(RuntimeContainer)
|
||||||
@@ -1512,21 +1530,18 @@ public:
|
|||||||
|
|
||||||
static QList<StoragePtr> createStorages(const ContainerNode &container);
|
static QList<StoragePtr> createStorages(const ContainerNode &container);
|
||||||
bool isStarting() const { return m_startGuard.isLocked(); }
|
bool isStarting() const { return m_startGuard.isLocked(); }
|
||||||
int continueIndex() const;
|
RuntimeIteration *parentIteration() const;
|
||||||
int currentLimit() const;
|
|
||||||
RuntimeContainer *parentContainer() const;
|
|
||||||
bool updateSuccessBit(bool success);
|
bool updateSuccessBit(bool success);
|
||||||
void deleteChild(RuntimeTask *node);
|
|
||||||
|
|
||||||
const ContainerNode &m_containerNode; // Not owning.
|
const ContainerNode &m_containerNode; // Not owning.
|
||||||
RuntimeTask *m_parentTask = nullptr; // Not owning.
|
RuntimeTask *m_parentTask = nullptr; // Not owning.
|
||||||
const QList<StoragePtr> m_storages;
|
const QList<StoragePtr> m_storages; // Owning.
|
||||||
|
|
||||||
std::vector<std::unique_ptr<RuntimeTask>> m_children; // Owning.
|
|
||||||
bool m_successBit = true;
|
bool m_successBit = true;
|
||||||
bool m_callStorageDoneHandlersOnDestruction = false;
|
bool m_callStorageDoneHandlersOnDestruction = false;
|
||||||
int m_doneCount = 0;
|
|
||||||
Guard m_startGuard;
|
Guard m_startGuard;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<RuntimeIteration>> m_iterations; // Owning.
|
||||||
};
|
};
|
||||||
|
|
||||||
class RuntimeTask
|
class RuntimeTask
|
||||||
@@ -1534,17 +1549,18 @@ class RuntimeTask
|
|||||||
Q_DISABLE_COPY(RuntimeTask)
|
Q_DISABLE_COPY(RuntimeTask)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RuntimeTask(const TaskNode &taskNode, RuntimeContainer *parentContainer)
|
|
||||||
: m_taskNode(taskNode)
|
|
||||||
, m_parentContainer(parentContainer)
|
|
||||||
{}
|
|
||||||
|
|
||||||
const TaskNode &m_taskNode; // Not owning.
|
const TaskNode &m_taskNode; // Not owning.
|
||||||
RuntimeContainer *m_parentContainer = nullptr; // Not owning.
|
RuntimeIteration *m_parentIteration = nullptr; // Not owning.
|
||||||
std::optional<RuntimeContainer> m_container; // Owning.
|
std::optional<RuntimeContainer> m_container = {}; // Owning.
|
||||||
std::unique_ptr<TaskInterface> m_task; // Owning.
|
std::unique_ptr<TaskInterface> m_task = {}; // Owning.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ExecutionContextActivator::activateContext(RuntimeIteration *iteration)
|
||||||
|
{
|
||||||
|
// TODO: activate iterator
|
||||||
|
activateContext(iteration->m_container);
|
||||||
|
}
|
||||||
|
|
||||||
void ExecutionContextActivator::activateContext(RuntimeContainer *container)
|
void ExecutionContextActivator::activateContext(RuntimeContainer *container)
|
||||||
{
|
{
|
||||||
const ContainerNode &containerNode = container->m_containerNode;
|
const ContainerNode &containerNode = container->m_containerNode;
|
||||||
@@ -1557,8 +1573,8 @@ void ExecutionContextActivator::activateContext(RuntimeContainer *container)
|
|||||||
}
|
}
|
||||||
// Go to the parent after activating this storages so that storage shadowing works
|
// Go to the parent after activating this storages so that storage shadowing works
|
||||||
// in the direction from child to parent root.
|
// in the direction from child to parent root.
|
||||||
if (container->parentContainer())
|
if (container->parentIteration())
|
||||||
activateContext(container->parentContainer());
|
activateContext(container->parentIteration());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskTreePrivate::start()
|
void TaskTreePrivate::start()
|
||||||
@@ -1572,7 +1588,7 @@ void TaskTreePrivate::start()
|
|||||||
QT_ASSERT(m_storages.contains(it.key()), qWarning("The registered storage doesn't "
|
QT_ASSERT(m_storages.contains(it.key()), qWarning("The registered storage doesn't "
|
||||||
"exist in task tree. Its handlers will never be called."));
|
"exist in task tree. Its handlers will never be called."));
|
||||||
}
|
}
|
||||||
m_runtimeRoot.reset(new RuntimeTask(*m_root, nullptr));
|
m_runtimeRoot.reset(new RuntimeTask{*m_root, nullptr});
|
||||||
start(m_runtimeRoot.get());
|
start(m_runtimeRoot.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1616,6 +1632,29 @@ void TaskTreePrivate::emitDone(DoneWith result)
|
|||||||
emit q->done(result);
|
emit q->done(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int RuntimeIteration::continueIndex() const
|
||||||
|
{
|
||||||
|
return m_doneCount ? qMin(m_doneCount + m_container->m_containerNode.m_parallelLimit - 1,
|
||||||
|
int(m_container->m_containerNode.m_children.size())) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RuntimeIteration::currentLimit() const
|
||||||
|
{
|
||||||
|
// TODO: Handle children well
|
||||||
|
const int childCount = int(m_container->m_containerNode.m_children.size());
|
||||||
|
return m_container->m_containerNode.m_parallelLimit
|
||||||
|
? qMin(m_doneCount + m_container->m_containerNode.m_parallelLimit, childCount) : childCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeIteration::deleteChild(RuntimeTask *task)
|
||||||
|
{
|
||||||
|
const auto it = std::find_if(m_children.cbegin(), m_children.cend(), [task](const auto &ptr) {
|
||||||
|
return ptr.get() == task;
|
||||||
|
});
|
||||||
|
if (it != m_children.cend())
|
||||||
|
m_children.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
static std::vector<TaskNode> createChildren(TaskTreePrivate *taskTreePrivate,
|
static std::vector<TaskNode> createChildren(TaskTreePrivate *taskTreePrivate,
|
||||||
const QList<GroupItem> &children)
|
const QList<GroupItem> &children)
|
||||||
{
|
{
|
||||||
@@ -1651,23 +1690,9 @@ QList<StoragePtr> RuntimeContainer::createStorages(const ContainerNode &containe
|
|||||||
return storages;
|
return storages;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RuntimeContainer::continueIndex() const
|
RuntimeIteration *RuntimeContainer::parentIteration() const
|
||||||
{
|
{
|
||||||
return m_doneCount ? qMin(m_doneCount + m_containerNode.m_parallelLimit - 1,
|
return m_parentTask->m_parentIteration;
|
||||||
int(m_containerNode.m_children.size())) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RuntimeContainer::currentLimit() const
|
|
||||||
{
|
|
||||||
// TODO: Handle children well
|
|
||||||
const int childCount = int(m_containerNode.m_children.size());
|
|
||||||
return m_containerNode.m_parallelLimit
|
|
||||||
? qMin(m_doneCount + m_containerNode.m_parallelLimit, childCount) : childCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
RuntimeContainer *RuntimeContainer::parentContainer() const
|
|
||||||
{
|
|
||||||
return m_parentTask->m_parentContainer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RuntimeContainer::updateSuccessBit(bool success)
|
bool RuntimeContainer::updateSuccessBit(bool success)
|
||||||
@@ -1686,15 +1711,6 @@ bool RuntimeContainer::updateSuccessBit(bool success)
|
|||||||
return m_successBit;
|
return m_successBit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RuntimeContainer::deleteChild(RuntimeTask *task)
|
|
||||||
{
|
|
||||||
const auto it = std::find_if(m_children.cbegin(), m_children.cend(), [task](const auto &ptr) {
|
|
||||||
return ptr.get() == task;
|
|
||||||
});
|
|
||||||
if (it != m_children.cend())
|
|
||||||
m_children.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetupResult TaskTreePrivate::start(RuntimeContainer *container)
|
SetupResult TaskTreePrivate::start(RuntimeContainer *container)
|
||||||
{
|
{
|
||||||
SetupResult startAction = SetupResult::Continue;
|
SetupResult startAction = SetupResult::Continue;
|
||||||
@@ -1718,14 +1734,14 @@ SetupResult TaskTreePrivate::continueStart(RuntimeContainer *container, SetupRes
|
|||||||
: startAction;
|
: startAction;
|
||||||
if (groupAction != SetupResult::Continue) {
|
if (groupAction != SetupResult::Continue) {
|
||||||
const bool bit = container->updateSuccessBit(groupAction == SetupResult::StopWithSuccess);
|
const bool bit = container->updateSuccessBit(groupAction == SetupResult::StopWithSuccess);
|
||||||
RuntimeContainer *parentContainer = container->parentContainer();
|
RuntimeIteration *parentIteration = container->parentIteration();
|
||||||
RuntimeTask *parentTask = container->m_parentTask;
|
RuntimeTask *parentTask = container->m_parentTask;
|
||||||
QT_CHECK(parentTask);
|
QT_CHECK(parentTask);
|
||||||
const bool result = invokeDoneHandler(container, bit ? DoneWith::Success : DoneWith::Error);
|
const bool result = invokeDoneHandler(container, bit ? DoneWith::Success : DoneWith::Error);
|
||||||
if (parentContainer) {
|
if (parentIteration) {
|
||||||
parentContainer->deleteChild(parentTask);
|
parentIteration->deleteChild(parentTask);
|
||||||
if (!parentContainer->isStarting())
|
if (!parentIteration->m_container->isStarting())
|
||||||
childDone(parentContainer, result);
|
childDone(parentIteration, result);
|
||||||
} else {
|
} else {
|
||||||
QT_CHECK(m_runtimeRoot.get() == parentTask);
|
QT_CHECK(m_runtimeRoot.get() == parentTask);
|
||||||
m_runtimeRoot.reset();
|
m_runtimeRoot.reset();
|
||||||
@@ -1737,39 +1753,49 @@ SetupResult TaskTreePrivate::continueStart(RuntimeContainer *container, SetupRes
|
|||||||
|
|
||||||
SetupResult TaskTreePrivate::startChildren(RuntimeContainer *container)
|
SetupResult TaskTreePrivate::startChildren(RuntimeContainer *container)
|
||||||
{
|
{
|
||||||
if (container->m_containerNode.m_parallelLimit == 0 && container->m_doneCount > 0)
|
if (container->m_containerNode.m_parallelLimit == 0 && !container->m_iterations.empty())
|
||||||
return SetupResult::Continue;
|
return SetupResult::Continue;
|
||||||
|
|
||||||
|
if (container->m_iterations.empty()) {
|
||||||
|
RuntimeIteration *iteration = new RuntimeIteration{0, container};
|
||||||
|
container->m_iterations.emplace_back(iteration);
|
||||||
|
}
|
||||||
|
|
||||||
GuardLocker locker(container->m_startGuard);
|
GuardLocker locker(container->m_startGuard);
|
||||||
for (int i = container->continueIndex(); i < int(container->m_containerNode.m_children.size()); ++i) {
|
for (auto &iteration : container->m_iterations) {
|
||||||
const int limit = container->currentLimit();
|
for (int i = iteration->continueIndex(); i < int(container->m_containerNode.m_children.size()); ++i) {
|
||||||
if (i >= limit)
|
const int limit = iteration->currentLimit();
|
||||||
break;
|
if (i >= limit)
|
||||||
|
break;
|
||||||
|
|
||||||
RuntimeTask *newTask = new RuntimeTask(container->m_containerNode.m_children.at(i), container);
|
RuntimeTask *newTask = new RuntimeTask{container->m_containerNode.m_children.at(i),
|
||||||
container->m_children.emplace_back(newTask);
|
iteration.get()};
|
||||||
|
iteration->m_children.emplace_back(newTask);
|
||||||
|
|
||||||
const SetupResult startAction = start(newTask);
|
const SetupResult startAction = start(newTask);
|
||||||
if (startAction == SetupResult::Continue)
|
if (startAction == SetupResult::Continue)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const SetupResult finalizeAction = childDone(container, startAction == SetupResult::StopWithSuccess);
|
const SetupResult finalizeAction = childDone(iteration.get(),
|
||||||
if (finalizeAction == SetupResult::Continue)
|
startAction == SetupResult::StopWithSuccess);
|
||||||
continue;
|
if (finalizeAction == SetupResult::Continue)
|
||||||
|
continue;
|
||||||
|
|
||||||
int skippedTaskCount = 0;
|
int skippedTaskCount = 0;
|
||||||
// Skip scheduled but not run yet. The current (i) was already notified.
|
// Skip scheduled but not run yet. The current (i) was already notified.
|
||||||
for (int j = i + 1; j < limit; ++j)
|
for (int j = i + 1; j < limit; ++j)
|
||||||
skippedTaskCount += container->m_containerNode.m_children.at(j).taskCount();
|
skippedTaskCount += container->m_containerNode.m_children.at(j).taskCount();
|
||||||
// TODO: Handle progress well
|
// TODO: Handle progress well
|
||||||
advanceProgress(skippedTaskCount);
|
advanceProgress(skippedTaskCount);
|
||||||
return finalizeAction;
|
return finalizeAction;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return SetupResult::Continue;
|
return SetupResult::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetupResult TaskTreePrivate::childDone(RuntimeContainer *container, bool success)
|
SetupResult TaskTreePrivate::childDone(RuntimeIteration *iteration, bool success)
|
||||||
{
|
{
|
||||||
|
RuntimeContainer *container = iteration->m_container;
|
||||||
const WorkflowPolicy &workflowPolicy = container->m_containerNode.m_workflowPolicy;
|
const WorkflowPolicy &workflowPolicy = container->m_containerNode.m_workflowPolicy;
|
||||||
const bool shouldStop = workflowPolicy == WorkflowPolicy::StopOnSuccessOrError
|
const bool shouldStop = workflowPolicy == WorkflowPolicy::StopOnSuccessOrError
|
||||||
|| (workflowPolicy == WorkflowPolicy::StopOnSuccess && success)
|
|| (workflowPolicy == WorkflowPolicy::StopOnSuccess && success)
|
||||||
@@ -1777,10 +1803,10 @@ SetupResult TaskTreePrivate::childDone(RuntimeContainer *container, bool success
|
|||||||
if (shouldStop)
|
if (shouldStop)
|
||||||
stop(container);
|
stop(container);
|
||||||
|
|
||||||
++container->m_doneCount;
|
++iteration->m_doneCount;
|
||||||
const bool updatedSuccess = container->updateSuccessBit(success);
|
const bool updatedSuccess = container->updateSuccessBit(success);
|
||||||
const SetupResult startAction
|
const SetupResult startAction
|
||||||
= (shouldStop || container->m_doneCount == int(container->m_containerNode.m_children.size()))
|
= (shouldStop || iteration->m_doneCount == int(container->m_containerNode.m_children.size()))
|
||||||
? toSetupResult(updatedSuccess) : SetupResult::Continue;
|
? toSetupResult(updatedSuccess) : SetupResult::Continue;
|
||||||
|
|
||||||
if (container->isStarting())
|
if (container->isStarting())
|
||||||
@@ -1790,14 +1816,17 @@ SetupResult TaskTreePrivate::childDone(RuntimeContainer *container, bool success
|
|||||||
|
|
||||||
void TaskTreePrivate::stop(RuntimeContainer *container)
|
void TaskTreePrivate::stop(RuntimeContainer *container)
|
||||||
{
|
{
|
||||||
for (auto &child : container->m_children)
|
|
||||||
stop(child.get());
|
|
||||||
|
|
||||||
int skippedTaskCount = 0;
|
int skippedTaskCount = 0;
|
||||||
for (int i = container->currentLimit(); i < int(container->m_containerNode.m_children.size()); ++i)
|
for (auto &iteration : container->m_iterations) {
|
||||||
skippedTaskCount += container->m_containerNode.m_children.at(i).taskCount();
|
for (auto &child : iteration->m_children)
|
||||||
|
stop(child.get());
|
||||||
|
// TODO: Do it only for 0-index iteration (up to root).
|
||||||
|
for (int i = iteration->currentLimit(); i < int(container->m_containerNode.m_children.size()); ++i)
|
||||||
|
skippedTaskCount += container->m_containerNode.m_children.at(i).taskCount();
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Handle progress well
|
// TODO: Handle progress well
|
||||||
|
// How to advance skipped tasks inside nested iterations?
|
||||||
advanceProgress(skippedTaskCount);
|
advanceProgress(skippedTaskCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1829,7 +1858,7 @@ SetupResult TaskTreePrivate::start(RuntimeTask *node)
|
|||||||
const GroupItem::TaskHandler &handler = node->m_taskNode.m_taskHandler;
|
const GroupItem::TaskHandler &handler = node->m_taskNode.m_taskHandler;
|
||||||
node->m_task.reset(handler.m_createHandler());
|
node->m_task.reset(handler.m_createHandler());
|
||||||
const SetupResult startAction = handler.m_setupHandler
|
const SetupResult startAction = handler.m_setupHandler
|
||||||
? invokeHandler(node->m_parentContainer, handler.m_setupHandler, *node->m_task.get())
|
? invokeHandler(node->m_parentIteration, handler.m_setupHandler, *node->m_task.get())
|
||||||
: SetupResult::Continue;
|
: SetupResult::Continue;
|
||||||
if (startAction != SetupResult::Continue) {
|
if (startAction != SetupResult::Continue) {
|
||||||
// TODO: Handle progress well
|
// TODO: Handle progress well
|
||||||
@@ -1844,12 +1873,12 @@ SetupResult TaskTreePrivate::start(RuntimeTask *node)
|
|||||||
const bool result = invokeDoneHandler(node, toDoneWith(doneResult));
|
const bool result = invokeDoneHandler(node, toDoneWith(doneResult));
|
||||||
QObject::disconnect(node->m_task.get(), &TaskInterface::done, q, nullptr);
|
QObject::disconnect(node->m_task.get(), &TaskInterface::done, q, nullptr);
|
||||||
node->m_task.release()->deleteLater();
|
node->m_task.release()->deleteLater();
|
||||||
RuntimeContainer *parentContainer = node->m_parentContainer;
|
RuntimeIteration *parentIteration = node->m_parentIteration;
|
||||||
parentContainer->deleteChild(node);
|
parentIteration->deleteChild(node);
|
||||||
if (parentContainer->isStarting())
|
if (parentIteration->m_container->isStarting())
|
||||||
*unwindAction = toSetupResult(result);
|
*unwindAction = toSetupResult(result);
|
||||||
else
|
else
|
||||||
childDone(parentContainer, result);
|
childDone(parentIteration, result);
|
||||||
});
|
});
|
||||||
|
|
||||||
node->m_task->start();
|
node->m_task->start();
|
||||||
@@ -1876,7 +1905,7 @@ bool TaskTreePrivate::invokeDoneHandler(RuntimeTask *node, DoneWith doneWith)
|
|||||||
DoneResult result = toDoneResult(doneWith);
|
DoneResult result = toDoneResult(doneWith);
|
||||||
const GroupItem::TaskHandler &handler = node->m_taskNode.m_taskHandler;
|
const GroupItem::TaskHandler &handler = node->m_taskNode.m_taskHandler;
|
||||||
if (handler.m_doneHandler && shouldCall(handler.m_callDoneIf, doneWith)) {
|
if (handler.m_doneHandler && shouldCall(handler.m_callDoneIf, doneWith)) {
|
||||||
result = invokeHandler(node->m_parentContainer,
|
result = invokeHandler(node->m_parentIteration,
|
||||||
handler.m_doneHandler, *node->m_task.get(), doneWith);
|
handler.m_doneHandler, *node->m_task.get(), doneWith);
|
||||||
}
|
}
|
||||||
// TODO: Handle progress well
|
// TODO: Handle progress well
|
||||||
|
Reference in New Issue
Block a user