diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index b4cfa7e2a4c..edec76bf83b 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -1280,6 +1280,11 @@ const GroupItem nullItem = GroupItem({}); const ExecutableItem successItem = Group { finishAllAndSuccess }; const ExecutableItem errorItem = Group { finishAllAndError }; +Group operator>>(const For &forItem, const Do &doItem) +{ + return {forItem.m_loop, doItem.m_children}; +} + // Please note the thread_local keyword below guarantees a separate instance per thread. // The s_activeTaskTrees is currently used internally only and is not exposed in the public API. // It serves for withLog() implementation now. Add a note here when a new usage is introduced. diff --git a/src/libs/solutions/tasking/tasktree.h b/src/libs/solutions/tasking/tasktree.h index 3cdff6fb8ae..b74ae378928 100644 --- a/src/libs/solutions/tasking/tasktree.h +++ b/src/libs/solutions/tasking/tasktree.h @@ -196,6 +196,10 @@ private: } }; +class Do; +class For; +class Group; + class TASKING_EXPORT GroupItem { public: @@ -274,8 +278,8 @@ protected: } private: + TASKING_EXPORT friend Group operator>>(const For &forItem, const Do &doItem); friend class ContainerNode; - friend class For; friend class TaskNode; friend class TaskTreePrivate; friend class ParallelLimitFunctor; @@ -435,42 +439,36 @@ TASKING_EXPORT extern const GroupItem nullItem; TASKING_EXPORT extern const ExecutableItem successItem; TASKING_EXPORT extern const ExecutableItem errorItem; -class TASKING_EXPORT For : public Group +class TASKING_EXPORT For final { public: - template - For(const Loop &loop, const Args &...args) - : Group(withLoop(loop, args...)) { } - -protected: - For(const Loop &loop, const QList &children) : Group({loop, children}) {} - For(const Loop &loop, std::initializer_list children) : Group({loop, children}) {} + explicit For(const Loop &loop) : m_loop(loop) {} private: - template - QList withLoop(const Loop &loop, const Args &...args) { - QList children{GroupItem(loop)}; - appendChildren(std::make_tuple(args...), &children); - return children; - } + TASKING_EXPORT friend Group operator>>(const For &forItem, const Do &doItem); - template - void appendChildren(const Tuple &tuple, QList *children) { - constexpr auto TupleSize = std::tuple_size_v; - if constexpr (TupleSize > 0) { - // static_assert(workflowPolicyCount() <= 1, "Too many workflow policies in one group."); - children->append(std::get(tuple)); - if constexpr (N + 1 < TupleSize) - appendChildren(tuple, children); - } - } + Loop m_loop; }; -class TASKING_EXPORT Forever final : public For +class TASKING_EXPORT Do final { public: - Forever(const QList &children) : For(LoopForever(), children) {} - Forever(std::initializer_list children) : For(LoopForever(), children) {} + explicit Do(const QList &children) : m_children(children) {} + explicit Do(std::initializer_list children) : m_children(children) {} + +private: + TASKING_EXPORT friend Group operator>>(const For &forItem, const Do &doItem); + + GroupItem m_children; +}; + +class TASKING_EXPORT Forever final : public ExecutableItem +{ +public: + explicit Forever(const QList &children) + { addChildren({ For (LoopForever()) >> Do { children } } ); } + explicit Forever(std::initializer_list children) + { addChildren({ For (LoopForever()) >> Do { children } } ); } }; // Synchronous invocation. Similarly to Group - isn't counted as a task inside taskCount() diff --git a/src/plugins/android/androidavdmanager.cpp b/src/plugins/android/androidavdmanager.cpp index 9fe8212ac35..19c8d69b0f7 100644 --- a/src/plugins/android/androidavdmanager.cpp +++ b/src/plugins/android/androidavdmanager.cpp @@ -138,8 +138,7 @@ static ExecutableItem serialNumberRecipe(const QString &avdName, const Storage> Do { parallel, stopOnSuccess, Group { diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp index f8551e7a971..1d5de995a73 100644 --- a/src/plugins/android/androiddeployqtstep.cpp +++ b/src/plugins/android/androiddeployqtstep.cpp @@ -417,13 +417,11 @@ GroupItem AndroidDeployQtStep::runRecipe() onGroupDone(onSerialNumberGroupDone) }, deployRecipe(), - For { - iterator, + For (iterator) >> Do { parallelIdealThreadCountLimit, AsyncTask(onRemoveFileSetup) }, - For { - iterator, + For (iterator) >> Do { ProcessTask(onAdbSetup, onAdbDone) } }; diff --git a/src/plugins/android/androiddevice.cpp b/src/plugins/android/androiddevice.cpp index de164f03c49..f42ca27f878 100644 --- a/src/plugins/android/androiddevice.cpp +++ b/src/plugins/android/androiddevice.cpp @@ -858,8 +858,7 @@ AndroidDeviceManagerInstance::AndroidDeviceManagerInstance(QObject *parent) // otherwise, Android Studio would give an error during parsing also. So this fix // aim to keep support for Qt Creator and Android Studio. - m_avdListRecipe = For { - iterator, + m_avdListRecipe = For (iterator) >> Do { storage, ProcessTask(onProcessSetup, onProcessDone) }; diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp index 3c43275bdb9..656d01839d6 100644 --- a/src/plugins/android/androidrunnerworker.cpp +++ b/src/plugins/android/androidrunnerworker.cpp @@ -582,8 +582,7 @@ static ExecutableItem preStartRecipe(RunnerStorage *storage) return Group { argsStorage, onGroupSetup(onArgsSetup), - For { - iterator, + For (iterator) >> Do { ProcessTask(onPreCommandSetup, onPreCommandDone, CallDoneIf::Error) }, Group { @@ -614,8 +613,7 @@ static ExecutableItem postDoneRecipe(RunnerStorage *storage) return Group { finishAllAndSuccess, - For { - iterator, + For (iterator) >> Do { ProcessTask(onProcessSetup) }, onGroupDone(onDone) @@ -674,8 +672,7 @@ static ExecutableItem uploadDebugServerRecipe(RunnerStorage *storage, const QStr return Group { tempDebugServerPathStorage, - For { - iterator, + For (iterator) >> Do { ProcessTask(onDeviceFileExistsSetup, onDeviceFileExistsDone) }, Sync(onTempDebugServerPath), diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp index 1a7db4ea49f..55a630fb0a9 100644 --- a/src/plugins/android/androidsdkmanager.cpp +++ b/src/plugins/android/androidsdkmanager.cpp @@ -294,13 +294,11 @@ static GroupItem installationRecipe(const Storage &dialogStorage, return Group { onGroupSetup(onSetup), - For { - uninstallIterator, + For (uninstallIterator) >> Do { finishAllAndSuccess, ProcessTask(onUninstallSetup, onDone) }, - For { - installIterator, + For (installIterator) >> Do { finishAllAndSuccess, ProcessTask(onInstallSetup, onDone) } diff --git a/src/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp index db32e10f235..9bf5cc6f091 100644 --- a/src/plugins/autotest/testcodeparser.cpp +++ b/src/plugins/autotest/testcodeparser.cpp @@ -417,8 +417,7 @@ void TestCodeParser::scanForTests(const QSet &filePaths, if (!results.isEmpty()) emit testParseResultsReady(results); }; - const For recipe { - LoopRepeat(filteredFiles.size()), + const Group recipe = For (LoopRepeat(filteredFiles.size())) >> Do { parallelLimit(limit), storage, onGroupSetup([storage, filteredFiles] { *storage = filteredFiles.cbegin(); }), diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp index 0c1d543cb7d..698903c1ed6 100644 --- a/src/plugins/autotest/testrunner.cpp +++ b/src/plugins/autotest/testrunner.cpp @@ -461,8 +461,7 @@ void TestRunner::runTestsHelper() } }; - const For recipe { - iterator, + const Group recipe = For (iterator) >> Do { finishAllAndSuccess, Group { storage, diff --git a/src/plugins/axivion/axivionplugin.cpp b/src/plugins/axivion/axivionplugin.cpp index 55e44582574..f1c7c7a8c2e 100644 --- a/src/plugins/axivion/axivionplugin.cpp +++ b/src/plugins/axivion/axivionplugin.cpp @@ -715,8 +715,7 @@ static Group authorizationRecipe() *serverUrlStorage = unauthorizedDashboardStorage->url; }), }, - For { - LoopUntil(onCredentialLoopCondition), + For (LoopUntil(onCredentialLoopCondition)) >> Do { CredentialQueryTask(onGetCredentialSetup, onGetCredentialDone), Group { passwordStorage, diff --git a/src/plugins/clangtools/clangtoolrunner.cpp b/src/plugins/clangtools/clangtoolrunner.cpp index 8fb6fdd67b2..082a111a7db 100644 --- a/src/plugins/clangtools/clangtoolrunner.cpp +++ b/src/plugins/clangtools/clangtoolrunner.cpp @@ -181,8 +181,7 @@ GroupItem clangToolTask(CppEditor::ClangToolType toolType, error}); }; - return For { - iterator, + return For (iterator) >> Do { parallelLimit(qMax(1, input.runSettings.parallelJobs())), finishAllAndSuccess, Group { diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.cpp b/src/plugins/coreplugin/locator/ilocatorfilter.cpp index 9d921866bb1..371a679d030 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/ilocatorfilter.cpp @@ -383,8 +383,7 @@ void LocatorMatcher::start() parallel, collectorStorage, AsyncTask(onCollectorSetup, onCollectorDone), - For { - iterator, + For (iterator) >> Do { parallelLimit(d->m_parallelLimit), TaskTreeTask(onTaskTreeSetup) } diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index b9097750666..1f62df2e592 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -142,8 +142,7 @@ DiffFilesController::DiffFilesController(IDocument *document) setDiffFiles(finalList); }; - const For recipe { - iterator, + const Group recipe = For (iterator) >> Do { parallelIdealThreadCountLimit, finishAllAndSuccess, storage, diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index f98caead913..871dcfd25f2 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -534,8 +534,7 @@ ShowController::ShowController(IDocument *document, const QString &id) updateDescription(*data); }; - const For recipe { - iterator, + const Group recipe = For (iterator) >> Do { parallel, continueOnSuccess, ProcessTask(onFollowSetup, onFollowDone, CallDoneIf::Success), diff --git a/src/plugins/lua/bindings/install.cpp b/src/plugins/lua/bindings/install.cpp index ca951ba743e..d6e5f7d7985 100644 --- a/src/plugins/lua/bindings/install.cpp +++ b/src/plugins/lua/bindings/install.cpp @@ -196,8 +196,7 @@ static Group installRecipe( return DoneResult::Success; }; - return For { - installOptionsIt, + return For (installOptionsIt) >> Do { storage, parallelIdealThreadCountLimit, Group{ diff --git a/src/plugins/projectexplorer/treescanner.cpp b/src/plugins/projectexplorer/treescanner.cpp index 369f2b56523..4587d913961 100644 --- a/src/plugins/projectexplorer/treescanner.cpp +++ b/src/plugins/projectexplorer/treescanner.cpp @@ -246,8 +246,7 @@ static QList scanForFilesHelper( } }; - const For recipe { - iterator, + const Group recipe = For (iterator) >> Do { Utils::HostOsInfo::isLinuxHost() ? parallelLimit(2) : parallelIdealThreadCountLimit, Utils::AsyncTask(onSetup, onDone) }; diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index 03e8ab38f19..558e31b6bdf 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -1646,13 +1646,11 @@ private: }; const Group recipe { - For { - iteratorParentDirs, + For (iteratorParentDirs) >> Do { parallelIdealThreadCountLimit, AsyncTask>(onCreateDirSetup, onCreateDirDone), }, - For { - iterator, + For (iterator) >> Do { parallelLimit(2), counterStorage, AsyncTask>(onCopySetup, onCopyDone), diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp index 897094490d0..7f1cf66b94f 100644 --- a/src/plugins/remotelinux/linuxdevicetester.cpp +++ b/src/plugins/remotelinux/linuxdevicetester.cpp @@ -278,8 +278,7 @@ GroupItem GenericLinuxDeviceTesterPrivate::commandTasks() const emit q->errorMessage(message); }; - return For { - iterator, + return For (iterator) >> Do { continueOnError, onGroupSetup([this] { emit q->progressMessage(Tr::tr("Checking if required commands are available...")); diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index 5a0b7849a1d..960e10b9cb8 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -2741,8 +2741,7 @@ void tst_Tasking::testTree_data() createSuccessTask(2) }; - const For rootSequentialSuccess { - LoopRepeat(2), + const Group rootSequentialSuccess = For (LoopRepeat(2)) >> Do { sequential, successItems }; @@ -2757,8 +2756,7 @@ void tst_Tasking::testTree_data() {2, Handler::Success} }; - const For rootParallelSuccess { - LoopRepeat(2), + const Group rootParallelSuccess = For (LoopRepeat(2)) >> Do { parallel, successItems }; @@ -2773,8 +2771,7 @@ void tst_Tasking::testTree_data() {2, Handler::Success} }; - const For rootParallelLimitSuccess { - LoopRepeat(2), + const Group rootParallelLimitSuccess = For (LoopRepeat(2)) >> Do { parallelLimit(2), successItems }; @@ -2795,8 +2792,7 @@ void tst_Tasking::testTree_data() createFailingTask(2) }; - const For rootSequentialError { - LoopRepeat(2), + const Group rootSequentialError = For (LoopRepeat(2)) >> Do { sequential, errorItems }; @@ -2807,8 +2803,7 @@ void tst_Tasking::testTree_data() {2, Handler::Error} }; - const For rootParallelError { - LoopRepeat(2), + const Group rootParallelError = For (LoopRepeat(2)) >> Do { parallel, errorItems }; @@ -2823,8 +2818,7 @@ void tst_Tasking::testTree_data() {2, Handler::Canceled} }; - const For rootParallelLimitError { - LoopRepeat(2), + const Group rootParallelLimitError = For (LoopRepeat(2)) >> Do { parallelLimit(2), errorItems }; @@ -2883,8 +2877,7 @@ void tst_Tasking::testTree_data() TestTask(onSetupStop(2), onDone(2)) }; - const For rootSequential { - loop, + const Group rootSequential = For(loop) >> Do { sequential, items }; @@ -2902,8 +2895,7 @@ void tst_Tasking::testTree_data() {22, Handler::Setup} }; - const For rootParallel { - loop, + const Group rootParallel = For(loop) >> Do { parallel, items }; @@ -2921,8 +2913,7 @@ void tst_Tasking::testTree_data() {21, Handler::Success} }; - const For rootParallelLimit { - loop, + const Group rootParallelLimit = For(loop) >> Do { parallelLimit(2), items }; @@ -2950,8 +2941,7 @@ void tst_Tasking::testTree_data() { // Check if task tree finishes with the right progress value when LoopUntil(false). - const For root { - LoopUntil([](int) { return false; }), + const Group root = For(LoopUntil([](int) { return false; })) >> Do { storage, createSuccessTask(1) }; @@ -2961,11 +2951,9 @@ void tst_Tasking::testTree_data() { // Check if task tree finishes with the right progress value when nested LoopUntil(false). - const For root { - LoopUntil([](int index) { return index < 2; }), + const Group root = For (LoopUntil([](int index) { return index < 2; })) >> Do { storage, - For { - LoopUntil([](int) { return false; }), + For (LoopUntil([](int) { return false; })) >> Do { createSuccessTask(1) } }; @@ -2975,13 +2963,12 @@ void tst_Tasking::testTree_data() { // 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 LoopUntil iterator([storage](int iteration) { + storage->m_log.append({iteration, Handler::Iteration}); + return iteration < 3; + }); + + const Group root = For(iterator) >> Do { storage }; const Log log { {0, Handler::Iteration}, @@ -3007,8 +2994,7 @@ void tst_Tasking::testTree_data() { // Check if task tree finishes with the right progress value when nested LoopUntil(false). - const For root { - LoopUntil([](int index) { return index < 2; }), + const Group root = For (LoopUntil([](int index) { return index < 2; })) >> Do { storage, Group { onGroupSetup([] { return SetupResult::StopWithSuccess; }), @@ -3186,8 +3172,7 @@ void tst_Tasking::testTree_data() return DoneResult::Error; }; - const For root { - iterator, + const Group root = For (iterator) >> Do { storage, parallel, TestTask(onSetup, onDone) diff --git a/tests/manual/subdirfilecontainer/tst_subdirfilecontainer.cpp b/tests/manual/subdirfilecontainer/tst_subdirfilecontainer.cpp index 8cbaad56474..6493bd9121c 100644 --- a/tests/manual/subdirfilecontainer/tst_subdirfilecontainer.cpp +++ b/tests/manual/subdirfilecontainer/tst_subdirfilecontainer.cpp @@ -149,8 +149,7 @@ private slots: parentDir.filePath(destDirName)); }; - const For recipe = { - iterator, + const Group recipe = For (iterator) >> Do { parallelIdealThreadCountLimit, // Parallelize tree generation AsyncTask(onCopySetup) }; @@ -169,8 +168,7 @@ private slots: parentDir.filePath(dirName(iterator.iteration() + 1))); }; - const For recipe = { - iterator, + const Group recipe = For (iterator) >> Do { parallelIdealThreadCountLimit, // Parallelize tree removal AsyncTask(onSetup) }; diff --git a/tests/manual/tasking/assetdownloader/assetdownloader.cpp b/tests/manual/tasking/assetdownloader/assetdownloader.cpp index b5daf6d4318..c7bb2b3f8be 100644 --- a/tests/manual/tasking/assetdownloader/assetdownloader.cpp +++ b/tests/manual/tasking/assetdownloader/assetdownloader.cpp @@ -509,8 +509,7 @@ void AssetDownloader::start() onGroupSetup(onSkipIfAllAssetsPresent), NetworkQueryTask(onZipDownloadSetup, onZipDownloadDone), ConcurrentCallTask(onUnzipSetup, onUnzipDone), - For { - downloadIterator, + For (downloadIterator) >> Do { parallelIdealThreadCountLimit, onGroupSetup(onAssetsDownloadGroupSetup), Group { @@ -519,8 +518,7 @@ void AssetDownloader::start() ConcurrentCallTask(onAssetWriteSetup, onAssetWriteDone) } }, - For { - copyIterator, + For (copyIterator) >> Do { parallelIdealThreadCountLimit, onGroupSetup(onAssetsCopyGroupSetup), ConcurrentCallTask(onAssetCopySetup, onAssetCopyDone) diff --git a/tests/manual/tasking/dataexchange/recipe.cpp b/tests/manual/tasking/dataexchange/recipe.cpp index c326d48d3e2..c068416bf52 100644 --- a/tests/manual/tasking/dataexchange/recipe.cpp +++ b/tests/manual/tasking/dataexchange/recipe.cpp @@ -74,8 +74,7 @@ Group recipe(const Storage &externalStorage) internalStorage, NetworkQueryTask(onDownloadSetup, onDownloadDone), ConcurrentCallTask(onReadSetup, onReadDone), - For { - repeater, + For (repeater) >> Do { parallelIdealThreadCountLimit, ConcurrentCallTask(onScaleSetup, onScaleDone) } diff --git a/tests/manual/tasking/imagescaling/imagescaling.cpp b/tests/manual/tasking/imagescaling/imagescaling.cpp index ca9840269d9..44390372175 100644 --- a/tests/manual/tasking/imagescaling/imagescaling.cpp +++ b/tests/manual/tasking/imagescaling/imagescaling.cpp @@ -93,8 +93,7 @@ void Images::process() labels[it]->setText(tr("Image\nData\nError.")); }; - const For recipe { - iterator, + const Group recipe = For (iterator) >> Do { finishAllAndSuccess, parallel, onGroupSetup(onRootSetup), diff --git a/tests/manual/tasking/trafficlight/main.cpp b/tests/manual/tasking/trafficlight/main.cpp index 161632c98d6..d4e8ba5d063 100644 --- a/tests/manual/tasking/trafficlight/main.cpp +++ b/tests/manual/tasking/trafficlight/main.cpp @@ -16,7 +16,7 @@ int main(int argc, char **argv) QApplication app(argc, argv); GlueInterface iface; - TaskTree taskTree(recipe(&iface)); + TaskTree taskTree({recipe(&iface)}); TrafficLight widget(&iface); widget.show(); diff --git a/tests/manual/tasking/trafficlight/recipe.cpp b/tests/manual/tasking/trafficlight/recipe.cpp index abc70715364..a5f7fc817af 100644 --- a/tests/manual/tasking/trafficlight/recipe.cpp +++ b/tests/manual/tasking/trafficlight/recipe.cpp @@ -11,7 +11,7 @@ using namespace Tasking; using namespace std::chrono; -Group recipe(GlueInterface *iface) +ExecutableItem recipe(GlueInterface *iface) { return Forever { finishAllAndSuccess, diff --git a/tests/manual/tasking/trafficlight/recipe.h b/tests/manual/tasking/trafficlight/recipe.h index 333e8b98f4c..bbf07c1e20b 100644 --- a/tests/manual/tasking/trafficlight/recipe.h +++ b/tests/manual/tasking/trafficlight/recipe.h @@ -4,10 +4,10 @@ #ifndef RECIPE_H #define RECIPE_H -namespace Tasking { class Group; } +namespace Tasking { class ExecutableItem; } class GlueInterface; -Tasking::Group recipe(GlueInterface *iface); +Tasking::ExecutableItem recipe(GlueInterface *iface); #endif // RECIPE_H