diff --git a/src/libs/utils/tasktree.cpp b/src/libs/utils/tasktree.cpp index f25545129ff..0ef5f18c624 100644 --- a/src/libs/utils/tasktree.cpp +++ b/src/libs/utils/tasktree.cpp @@ -67,8 +67,8 @@ void TreeStorageBase::activateStorage(int id) m_storageData->m_activeStorage = id; } -Execute sequential(ExecuteMode::Sequential); -Execute parallel(ExecuteMode::Parallel); +ParallelLimit sequential(1); +ParallelLimit parallel(0); Workflow stopOnError(WorkflowPolicy::StopOnError); Workflow continueOnError(WorkflowPolicy::ContinueOnError); Workflow stopOnDone(WorkflowPolicy::StopOnDone); @@ -83,10 +83,10 @@ void TaskItem::addChildren(const QList &children) case Type::Group: m_children.append(child); break; - case Type::Mode: + case Type::Limit: QTC_ASSERT(m_type == Type::Group, qWarning("Mode may only be a child of Group, skipping..."); return); - m_executeMode = child.m_executeMode; // TODO: Assert on redefinition? + m_parallelLimit = child.m_parallelLimit; // TODO: Assert on redefinition? break; case Type::Policy: QTC_ASSERT(m_type == Type::Group, @@ -161,7 +161,7 @@ public: TaskTreePrivate *m_taskTreePrivate = nullptr; TaskContainer *m_parentContainer = nullptr; - const ExecuteMode m_executeMode = ExecuteMode::Parallel; + const int m_parallelLimit = 1; WorkflowPolicy m_workflowPolicy = WorkflowPolicy::StopOnError; const TaskItem::GroupHandler m_groupHandler; QList m_storageList; @@ -314,7 +314,7 @@ TaskContainer::TaskContainer(TaskTreePrivate *taskTreePrivate, TaskContainer *pa const TaskItem &task) : m_taskTreePrivate(taskTreePrivate) , m_parentContainer(parentContainer) - , m_executeMode(task.executeMode()) + , m_parallelLimit(task.parallelLimit()) , m_workflowPolicy(task.workflowPolicy()) , m_groupHandler(task.groupHandler()) , m_storageList(taskTreePrivate->addStorages(task.storageList())) @@ -353,7 +353,8 @@ void TaskContainer::start() } } - if (m_groupConfig.action == GroupAction::StopWithDone || m_groupConfig.action == GroupAction::StopWithError) { + if (m_groupConfig.action == GroupAction::StopWithDone + || m_groupConfig.action == GroupAction::StopWithError) { const bool success = m_groupConfig.action == GroupAction::StopWithDone; const int skippedTaskCount = taskCount(); m_taskTreePrivate->advanceProgress(skippedTaskCount); @@ -369,17 +370,12 @@ void TaskContainer::start() return; } - m_currentIndex = 0; resetSuccessBit(); - if (m_executeMode == ExecuteMode::Sequential) { - m_selectedChildren.at(m_currentIndex)->start(); - return; - } - - // Parallel case - for (TaskNode *child : std::as_const(m_selectedChildren)) { - if (!child->start()) + const int childCount = m_selectedChildren.size(); + const int startCount = m_parallelLimit ? qMin(m_parallelLimit, childCount) : childCount; + for (int i = 0; i < startCount; ++i) { + if (!m_selectedChildren.at(i)->start()) // TODO: take m_groupConfig.action into account return; } } @@ -406,9 +402,9 @@ void TaskContainer::stop() if (!isRunning()) return; - if (m_executeMode == ExecuteMode::Sequential) { + if (m_parallelLimit) { // skip not started tasks int skippedTaskCount = 0; - for (int i = m_currentIndex + 1; i < m_selectedChildren.size(); ++i) + for (int i = m_currentIndex + m_parallelLimit; i < m_selectedChildren.size(); ++i) skippedTaskCount += m_selectedChildren.at(i)->taskCount(); m_taskTreePrivate->advanceProgress(skippedTaskCount); } @@ -445,8 +441,12 @@ void TaskContainer::childDone(bool success) return; } - if (m_executeMode == ExecuteMode::Sequential) - m_selectedChildren.at(m_currentIndex)->start(); + if (m_parallelLimit == 0) + return; + + const int nextIndexToRun = m_currentIndex + m_parallelLimit - 1; + if (nextIndexToRun < m_selectedChildren.size()) + m_selectedChildren.at(nextIndexToRun)->start(); } void TaskContainer::invokeEndHandler(bool success, bool propagateToParent) diff --git a/src/libs/utils/tasktree.h b/src/libs/utils/tasktree.h index e95ee9fb54d..c67238dc46e 100644 --- a/src/libs/utils/tasktree.h +++ b/src/libs/utils/tasktree.h @@ -85,11 +85,6 @@ private: } }; -enum class ExecuteMode { - Sequential, // default - Parallel -}; - // 4 policies: // 1. When all children finished with done -> report done, otherwise: // a) Report error on first error and stop executing other children (including their subtree) @@ -134,8 +129,6 @@ public: using GroupSimpleHandler = std::function; // Called when group entered using GroupSetupHandler = std::function; - // Called after group ended with success or failure, passed set of successful children -// using GroupEndHandler = std::function &)>; struct TaskHandler { TaskCreateHandler m_createHandler; @@ -151,7 +144,7 @@ public: GroupSetupHandler m_dynamicSetupHandler = {}; }; - ExecuteMode executeMode() const { return m_executeMode; } + int parallelLimit() const { return m_parallelLimit; } WorkflowPolicy workflowPolicy() const { return m_workflowPolicy; } TaskHandler taskHandler() const { return m_taskHandler; } GroupHandler groupHandler() const { return m_groupHandler; } @@ -162,16 +155,16 @@ protected: enum class Type { Group, Storage, - Mode, + Limit, Policy, TaskHandler, GroupHandler }; TaskItem() = default; - TaskItem(ExecuteMode mode) - : m_type(Type::Mode) - , m_executeMode(mode) {} + TaskItem(int parallelLimit) + : m_type(Type::Limit) + , m_parallelLimit(parallelLimit) {} TaskItem(WorkflowPolicy policy) : m_type(Type::Policy) , m_workflowPolicy(policy) {} @@ -188,7 +181,7 @@ protected: private: Type m_type = Type::Group; - ExecuteMode m_executeMode = ExecuteMode::Sequential; + int m_parallelLimit = 1; // 0 means unlimited WorkflowPolicy m_workflowPolicy = WorkflowPolicy::StopOnError; TaskHandler m_taskHandler; GroupHandler m_groupHandler; @@ -209,10 +202,10 @@ public: Storage(const TreeStorageBase &storage) : TaskItem(storage) { } }; -class QTCREATOR_UTILS_EXPORT Execute : public TaskItem +class QTCREATOR_UTILS_EXPORT ParallelLimit : public TaskItem { public: - Execute(ExecuteMode mode) : TaskItem(mode) {} + ParallelLimit(int parallelLimit) : TaskItem(qMax(parallelLimit, 0)) {} }; class QTCREATOR_UTILS_EXPORT Workflow : public TaskItem @@ -245,8 +238,8 @@ public: DynamicSetup(const GroupSetupHandler &handler) : TaskItem({{}, {}, {}, handler}) {} }; -QTCREATOR_UTILS_EXPORT extern Execute sequential; -QTCREATOR_UTILS_EXPORT extern Execute parallel; +QTCREATOR_UTILS_EXPORT extern ParallelLimit sequential; +QTCREATOR_UTILS_EXPORT extern ParallelLimit parallel; QTCREATOR_UTILS_EXPORT extern Workflow stopOnError; QTCREATOR_UTILS_EXPORT extern Workflow continueOnError; QTCREATOR_UTILS_EXPORT extern Workflow stopOnDone; diff --git a/tests/manual/tasktree/main.cpp b/tests/manual/tasktree/main.cpp index e0a00483749..b57481bfc41 100644 --- a/tests/manual/tasktree/main.cpp +++ b/tests/manual/tasktree/main.cpp @@ -102,7 +102,7 @@ int main(int argc, char *argv[]) groupTask_1->setWorkflowPolicy(Tasking::WorkflowPolicy::ContinueOnDone); groupTask_4->setWorkflowPolicy(Tasking::WorkflowPolicy::Optional); - groupTask_4_3->setExecuteMode(Tasking::ExecuteMode::Parallel); + groupTask_4_3->setExecuteMode(ExecuteMode::Parallel); groupTask_4_3->setWorkflowPolicy(Tasking::WorkflowPolicy::StopOnError); // Task layout @@ -170,14 +170,14 @@ int main(int argc, char *argv[]) }; const Group root { - Execute(rootGroup->executeMode()), + rootGroup->executeMode(), Workflow(rootGroup->workflowPolicy()), OnGroupSetup([rootGroup] { rootGroup->setState(State::Running); }), OnGroupDone([rootGroup] { rootGroup->setState(State::Done); }), OnGroupError([rootGroup] { rootGroup->setState(State::Error); }), Group { - Execute(groupTask_1->executeMode()), + groupTask_1->executeMode(), Workflow(groupTask_1->workflowPolicy()), OnGroupSetup([groupTask_1] { groupTask_1->setState(State::Running); }), OnGroupDone([groupTask_1] { groupTask_1->setState(State::Done); }), @@ -190,7 +190,7 @@ int main(int argc, char *argv[]) taskItem(task_2), taskItem(task_3), Group { - Execute(groupTask_4->executeMode()), + groupTask_4->executeMode(), Workflow(groupTask_4->workflowPolicy()), OnGroupSetup([groupTask_4] { groupTask_4->setState(State::Running); }), OnGroupDone([groupTask_4] { groupTask_4->setState(State::Done); }), @@ -199,7 +199,7 @@ int main(int argc, char *argv[]) taskItem(task_4_1), taskItem(task_4_2), Group { - Execute(groupTask_4_3->executeMode()), + groupTask_4_3->executeMode(), Workflow(groupTask_4_3->workflowPolicy()), OnGroupSetup([groupTask_4_3] { groupTask_4_3->setState(State::Running); }), OnGroupDone([groupTask_4_3] { groupTask_4_3->setState(State::Done); }), diff --git a/tests/manual/tasktree/taskwidget.cpp b/tests/manual/tasktree/taskwidget.cpp index a6901f8d136..d4ddc0194a9 100644 --- a/tests/manual/tasktree/taskwidget.cpp +++ b/tests/manual/tasktree/taskwidget.cpp @@ -121,11 +121,11 @@ GroupWidget::GroupWidget() { m_stateIndicator->setFixedWidth(30); - m_executeCombo->addItem("Sequential", (int)Tasking::ExecuteMode::Sequential); - m_executeCombo->addItem("Parallel", (int)Tasking::ExecuteMode::Parallel); + m_executeCombo->addItem("Sequential", (int)ExecuteMode::Sequential); + m_executeCombo->addItem("Parallel", (int)ExecuteMode::Parallel); updateExecuteMode(); connect(m_executeCombo, &QComboBox::currentIndexChanged, this, [this](int index) { - m_executeMode = (Tasking::ExecuteMode)m_executeCombo->itemData(index).toInt(); + m_executeMode = (ExecuteMode)m_executeCombo->itemData(index).toInt(); }); m_workflowCombo->addItem("Stop On Error", (int)Tasking::WorkflowPolicy::StopOnError); @@ -152,7 +152,7 @@ GroupWidget::GroupWidget() setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); } -void GroupWidget::setExecuteMode(Tasking::ExecuteMode mode) +void GroupWidget::setExecuteMode(ExecuteMode mode) { m_executeMode = mode; updateExecuteMode(); @@ -163,9 +163,9 @@ void GroupWidget::updateExecuteMode() m_executeCombo->setCurrentIndex(m_executeCombo->findData((int)m_executeMode)); } -Tasking::ExecuteMode GroupWidget::executeMode() const +Tasking::ParallelLimit GroupWidget::executeMode() const { - return m_executeMode; + return m_executeMode == ExecuteMode::Sequential ? Tasking::sequential : Tasking::parallel; } void GroupWidget::setWorkflowPolicy(Tasking::WorkflowPolicy policy) diff --git a/tests/manual/tasktree/taskwidget.h b/tests/manual/tasktree/taskwidget.h index be21ae02e9a..7421ca5a30b 100644 --- a/tests/manual/tasktree/taskwidget.h +++ b/tests/manual/tasktree/taskwidget.h @@ -22,6 +22,11 @@ enum class State { Error }; +enum class ExecuteMode { + Sequential, // default + Parallel +}; + class StateWidget : public QWidget { public: @@ -54,8 +59,8 @@ class GroupWidget : public StateWidget public: GroupWidget(); - void setExecuteMode(Utils::Tasking::ExecuteMode mode); - Utils::Tasking::ExecuteMode executeMode() const; + void setExecuteMode(ExecuteMode mode); + Utils::Tasking::ParallelLimit executeMode() const; void setWorkflowPolicy(Utils::Tasking::WorkflowPolicy policy); Utils::Tasking::WorkflowPolicy workflowPolicy() const; @@ -67,7 +72,7 @@ private: QComboBox *m_executeCombo = nullptr; QComboBox *m_workflowCombo = nullptr; - Utils::Tasking::ExecuteMode m_executeMode = Utils::Tasking::ExecuteMode::Sequential; + ExecuteMode m_executeMode = ExecuteMode::Sequential; Utils::Tasking::WorkflowPolicy m_workflowPolicy = Utils::Tasking::WorkflowPolicy::StopOnError; };