forked from qt-creator/qt-creator
TaskTree: Refactor For loops
Make the syntax more consistent with conditional API. Change-Id: I52353d0a0044252e1e3bac0b424ac7c22d927262 Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
@@ -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.
|
||||
|
@@ -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 <typename ...Args>
|
||||
For(const Loop &loop, const Args &...args)
|
||||
: Group(withLoop(loop, args...)) { }
|
||||
|
||||
protected:
|
||||
For(const Loop &loop, const QList<GroupItem> &children) : Group({loop, children}) {}
|
||||
For(const Loop &loop, std::initializer_list<GroupItem> children) : Group({loop, children}) {}
|
||||
explicit For(const Loop &loop) : m_loop(loop) {}
|
||||
|
||||
private:
|
||||
template <typename ...Args>
|
||||
QList<GroupItem> withLoop(const Loop &loop, const Args &...args) {
|
||||
QList<GroupItem> children{GroupItem(loop)};
|
||||
appendChildren(std::make_tuple(args...), &children);
|
||||
return children;
|
||||
}
|
||||
TASKING_EXPORT friend Group operator>>(const For &forItem, const Do &doItem);
|
||||
|
||||
template <typename Tuple, std::size_t N = 0>
|
||||
void appendChildren(const Tuple &tuple, QList<GroupItem> *children) {
|
||||
constexpr auto TupleSize = std::tuple_size_v<Tuple>;
|
||||
if constexpr (TupleSize > 0) {
|
||||
// static_assert(workflowPolicyCount<Tuple>() <= 1, "Too many workflow policies in one group.");
|
||||
children->append(std::get<N>(tuple));
|
||||
if constexpr (N + 1 < TupleSize)
|
||||
appendChildren<Tuple, N + 1>(tuple, children);
|
||||
}
|
||||
}
|
||||
Loop m_loop;
|
||||
};
|
||||
|
||||
class TASKING_EXPORT Forever final : public For
|
||||
class TASKING_EXPORT Do final
|
||||
{
|
||||
public:
|
||||
Forever(const QList<GroupItem> &children) : For(LoopForever(), children) {}
|
||||
Forever(std::initializer_list<GroupItem> children) : For(LoopForever(), children) {}
|
||||
explicit Do(const QList<GroupItem> &children) : m_children(children) {}
|
||||
explicit Do(std::initializer_list<GroupItem> 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<GroupItem> &children)
|
||||
{ addChildren({ For (LoopForever()) >> Do { children } } ); }
|
||||
explicit Forever(std::initializer_list<GroupItem> children)
|
||||
{ addChildren({ For (LoopForever()) >> Do { children } } ); }
|
||||
};
|
||||
|
||||
// Synchronous invocation. Similarly to Group - isn't counted as a task inside taskCount()
|
||||
|
@@ -138,8 +138,7 @@ static ExecutableItem serialNumberRecipe(const QString &avdName, const Storage<Q
|
||||
return Group {
|
||||
outputStorage,
|
||||
AndroidConfig::devicesCommandOutputRecipe(outputStorage),
|
||||
For {
|
||||
iterator,
|
||||
For (iterator) >> Do {
|
||||
parallel,
|
||||
stopOnSuccess,
|
||||
Group {
|
||||
|
@@ -417,13 +417,11 @@ GroupItem AndroidDeployQtStep::runRecipe()
|
||||
onGroupDone(onSerialNumberGroupDone)
|
||||
},
|
||||
deployRecipe(),
|
||||
For {
|
||||
iterator,
|
||||
For (iterator) >> Do {
|
||||
parallelIdealThreadCountLimit,
|
||||
AsyncTask<void>(onRemoveFileSetup)
|
||||
},
|
||||
For {
|
||||
iterator,
|
||||
For (iterator) >> Do {
|
||||
ProcessTask(onAdbSetup, onAdbDone)
|
||||
}
|
||||
};
|
||||
|
@@ -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)
|
||||
};
|
||||
|
@@ -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),
|
||||
|
@@ -294,13 +294,11 @@ static GroupItem installationRecipe(const Storage<DialogStorage> &dialogStorage,
|
||||
|
||||
return Group {
|
||||
onGroupSetup(onSetup),
|
||||
For {
|
||||
uninstallIterator,
|
||||
For (uninstallIterator) >> Do {
|
||||
finishAllAndSuccess,
|
||||
ProcessTask(onUninstallSetup, onDone)
|
||||
},
|
||||
For {
|
||||
installIterator,
|
||||
For (installIterator) >> Do {
|
||||
finishAllAndSuccess,
|
||||
ProcessTask(onInstallSetup, onDone)
|
||||
}
|
||||
|
@@ -417,8 +417,7 @@ void TestCodeParser::scanForTests(const QSet<FilePath> &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(); }),
|
||||
|
@@ -461,8 +461,7 @@ void TestRunner::runTestsHelper()
|
||||
}
|
||||
};
|
||||
|
||||
const For recipe {
|
||||
iterator,
|
||||
const Group recipe = For (iterator) >> Do {
|
||||
finishAllAndSuccess,
|
||||
Group {
|
||||
storage,
|
||||
|
@@ -715,8 +715,7 @@ static Group authorizationRecipe()
|
||||
*serverUrlStorage = unauthorizedDashboardStorage->url;
|
||||
}),
|
||||
},
|
||||
For {
|
||||
LoopUntil(onCredentialLoopCondition),
|
||||
For (LoopUntil(onCredentialLoopCondition)) >> Do {
|
||||
CredentialQueryTask(onGetCredentialSetup, onGetCredentialDone),
|
||||
Group {
|
||||
passwordStorage,
|
||||
|
@@ -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 {
|
||||
|
@@ -383,8 +383,7 @@ void LocatorMatcher::start()
|
||||
parallel,
|
||||
collectorStorage,
|
||||
AsyncTask<LocatorFilterEntries>(onCollectorSetup, onCollectorDone),
|
||||
For {
|
||||
iterator,
|
||||
For (iterator) >> Do {
|
||||
parallelLimit(d->m_parallelLimit),
|
||||
TaskTreeTask(onTaskTreeSetup)
|
||||
}
|
||||
|
@@ -142,8 +142,7 @@ DiffFilesController::DiffFilesController(IDocument *document)
|
||||
setDiffFiles(finalList);
|
||||
};
|
||||
|
||||
const For recipe {
|
||||
iterator,
|
||||
const Group recipe = For (iterator) >> Do {
|
||||
parallelIdealThreadCountLimit,
|
||||
finishAllAndSuccess,
|
||||
storage,
|
||||
|
@@ -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),
|
||||
|
@@ -196,8 +196,7 @@ static Group installRecipe(
|
||||
return DoneResult::Success;
|
||||
};
|
||||
|
||||
return For {
|
||||
installOptionsIt,
|
||||
return For (installOptionsIt) >> Do {
|
||||
storage,
|
||||
parallelIdealThreadCountLimit,
|
||||
Group{
|
||||
|
@@ -246,8 +246,7 @@ static QList<FileNode *> scanForFilesHelper(
|
||||
}
|
||||
};
|
||||
|
||||
const For recipe {
|
||||
iterator,
|
||||
const Group recipe = For (iterator) >> Do {
|
||||
Utils::HostOsInfo::isLinuxHost() ? parallelLimit(2) : parallelIdealThreadCountLimit,
|
||||
Utils::AsyncTask<DirectoryScanResult>(onSetup, onDone)
|
||||
};
|
||||
|
@@ -1646,13 +1646,11 @@ private:
|
||||
};
|
||||
|
||||
const Group recipe {
|
||||
For {
|
||||
iteratorParentDirs,
|
||||
For (iteratorParentDirs) >> Do {
|
||||
parallelIdealThreadCountLimit,
|
||||
AsyncTask<expected_str<void>>(onCreateDirSetup, onCreateDirDone),
|
||||
},
|
||||
For {
|
||||
iterator,
|
||||
For (iterator) >> Do {
|
||||
parallelLimit(2),
|
||||
counterStorage,
|
||||
AsyncTask<expected_str<void>>(onCopySetup, onCopyDone),
|
||||
|
@@ -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..."));
|
||||
|
@@ -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)
|
||||
|
@@ -149,8 +149,7 @@ private slots:
|
||||
parentDir.filePath(destDirName));
|
||||
};
|
||||
|
||||
const For recipe = {
|
||||
iterator,
|
||||
const Group recipe = For (iterator) >> Do {
|
||||
parallelIdealThreadCountLimit, // Parallelize tree generation
|
||||
AsyncTask<void>(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<void>(onSetup)
|
||||
};
|
||||
|
@@ -509,8 +509,7 @@ void AssetDownloader::start()
|
||||
onGroupSetup(onSkipIfAllAssetsPresent),
|
||||
NetworkQueryTask(onZipDownloadSetup, onZipDownloadDone),
|
||||
ConcurrentCallTask<void>(onUnzipSetup, onUnzipDone),
|
||||
For {
|
||||
downloadIterator,
|
||||
For (downloadIterator) >> Do {
|
||||
parallelIdealThreadCountLimit,
|
||||
onGroupSetup(onAssetsDownloadGroupSetup),
|
||||
Group {
|
||||
@@ -519,8 +518,7 @@ void AssetDownloader::start()
|
||||
ConcurrentCallTask<void>(onAssetWriteSetup, onAssetWriteDone)
|
||||
}
|
||||
},
|
||||
For {
|
||||
copyIterator,
|
||||
For (copyIterator) >> Do {
|
||||
parallelIdealThreadCountLimit,
|
||||
onGroupSetup(onAssetsCopyGroupSetup),
|
||||
ConcurrentCallTask<void>(onAssetCopySetup, onAssetCopyDone)
|
||||
|
@@ -74,8 +74,7 @@ Group recipe(const Storage<ExternalData> &externalStorage)
|
||||
internalStorage,
|
||||
NetworkQueryTask(onDownloadSetup, onDownloadDone),
|
||||
ConcurrentCallTask<QImage>(onReadSetup, onReadDone),
|
||||
For {
|
||||
repeater,
|
||||
For (repeater) >> Do {
|
||||
parallelIdealThreadCountLimit,
|
||||
ConcurrentCallTask<QImage>(onScaleSetup, onScaleDone)
|
||||
}
|
||||
|
@@ -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),
|
||||
|
@@ -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();
|
||||
|
@@ -11,7 +11,7 @@
|
||||
using namespace Tasking;
|
||||
using namespace std::chrono;
|
||||
|
||||
Group recipe(GlueInterface *iface)
|
||||
ExecutableItem recipe(GlueInterface *iface)
|
||||
{
|
||||
return Forever {
|
||||
finishAllAndSuccess,
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user