TaskTree: Add Task c'tor taking one handler for done and error

The overloaded c'tor takes one done handler with an additional
"bool success" argument.

Task-number: QTCREATORBUG-29834
Change-Id: Id579d055721a2a07a5a9f0900aa4a73655f21610
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-10-31 17:03:48 +01:00
parent 09c4aad0eb
commit d35d0b5100
4 changed files with 51 additions and 45 deletions

View File

@@ -324,6 +324,7 @@ public:
static_assert(std::is_base_of_v<TaskAdapter<Task, Deleter>, Adapter>,
"The Adapter type for the CustomTask<Adapter> needs to be derived from "
"TaskAdapter<Task>.");
using DoneHandler = std::function<void(const Task &, bool)>;
using EndHandler = std::function<void(const Task &)>;
static Adapter *createAdapter() { return new Adapter; }
CustomTask() : GroupItem({&createAdapter}) {}
@@ -332,6 +333,11 @@ public:
: GroupItem({&createAdapter, wrapSetup(std::forward<SetupHandler>(setup)),
wrapEnds(done, error)}) {}
template <typename SetupHandler>
CustomTask(SetupHandler &&setup, const DoneHandler &done)
: GroupItem({&createAdapter, wrapSetup(std::forward<SetupHandler>(setup)), wrapDone(done)})
{}
GroupItem withTimeout(std::chrono::milliseconds timeout,
const GroupEndHandler &handler = {}) const {
return GroupItem::withTimeout(*this, timeout, handler);
@@ -366,6 +372,15 @@ private:
handler(*adapter.task());
};
};
static TaskDoneHandler wrapDone(const DoneHandler &handler) {
if (!handler)
return {};
return [handler](const TaskInterface &taskInterface, bool success) {
const Adapter &adapter = static_cast<const Adapter &>(taskInterface);
handler(*adapter.task(), success);
};
};
};
class TaskTreePrivate;

View File

@@ -113,24 +113,22 @@ DiffFilesController::DiffFilesController(IDocument *document)
const auto setupTree = [this, storage](TaskTree &taskTree) {
QList<std::optional<FileData>> *outputList = storage.activeStorage();
const auto setupDiff = [this](Async<FileData> &async, const ReloadInput &reloadInput) {
const QList<ReloadInput> inputList = reloadInputList();
outputList->resize(inputList.size());
QList<GroupItem> tasks { parallel, finishAllAndDone };
for (int i = 0; i < inputList.size(); ++i) {
const auto setupDiff = [this, reloadInput = inputList.at(i)](Async<FileData> &async) {
async.setConcurrentCallData(
DiffFile(ignoreWhitespace(), contextLineCount()), reloadInput);
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
};
const auto onDiffDone = [outputList](const Async<FileData> &async, int i) {
const auto onDiffDone = [outputList, i](const Async<FileData> &async) {
if (async.isResultAvailable())
(*outputList)[i] = async.result();
};
const QList<ReloadInput> inputList = reloadInputList();
outputList->resize(inputList.size());
using namespace std::placeholders;
QList<GroupItem> tasks {parallel, finishAllAndDone};
for (int i = 0; i < inputList.size(); ++i) {
tasks.append(AsyncTask<FileData>(std::bind(setupDiff, _1, inputList.at(i)),
std::bind(onDiffDone, _1, i)));
tasks.append(AsyncTask<FileData>(setupDiff, onDiffDone));
}
taskTree.setRecipe(tasks);
};

View File

@@ -497,23 +497,21 @@ ShowController::ShowController(IDocument *document, const QString &id)
data->m_follows = {busyMessage};
data->m_follows.resize(parents.size());
const auto setupFollow = [this](Process &process, const QString &parent) {
setupCommand(process, {"describe", "--tags", "--abbrev=0", parent});
};
const auto onFollowDone = [data, updateDescription](const Process &process, int index) {
data->m_follows[index] = process.cleanedStdOut().trimmed();
updateDescription(*data);
};
const auto onFollowsError = [data, updateDescription] {
data->m_follows.clear();
updateDescription(*data);
};
using namespace std::placeholders;
QList<GroupItem> tasks {parallel, continueOnDone, onGroupError(onFollowsError)};
QList<GroupItem> tasks { parallel, continueOnDone, onGroupError(onFollowsError) };
for (int i = 0, total = parents.size(); i < total; ++i) {
tasks.append(ProcessTask(std::bind(setupFollow, _1, parents.at(i)),
std::bind(onFollowDone, _1, i)));
const auto setupFollow = [this, parent = parents.at(i)](Process &process) {
setupCommand(process, {"describe", "--tags", "--abbrev=0", parent});
};
const auto onFollowDone = [data, updateDescription, i](const Process &process) {
data->m_follows[i] = process.cleanedStdOut().trimmed();
updateDescription(*data);
};
tasks.append(ProcessTask(setupFollow, onFollowDone));
}
taskTree.setRecipe(tasks);
};

View File

@@ -111,14 +111,16 @@ void tst_Tasking::validConstructs()
};
const auto setupHandler = [](TaskObject &) {};
const auto doneHandler = [](const TaskObject &) {};
const auto finishHandler = [](const TaskObject &) {};
const auto errorHandler = [](const TaskObject &) {};
const auto doneHandler = [](const TaskObject &, bool) {};
const Group task2 {
parallel,
TestTask(setupHandler),
TestTask(setupHandler, finishHandler),
TestTask(setupHandler, finishHandler, errorHandler),
TestTask(setupHandler, doneHandler),
TestTask(setupHandler, doneHandler, errorHandler),
// need to explicitly pass empty handler for done
TestTask(setupHandler, {}, errorHandler)
};
@@ -220,14 +222,8 @@ void tst_Tasking::testTree_data()
};
const auto setupDone = [storage](int taskId) {
return [storage, taskId](const TaskObject &) {
storage->m_log.append({taskId, Handler::Done});
};
};
const auto setupError = [storage](int taskId) {
return [storage, taskId](const TaskObject &) {
storage->m_log.append({taskId, Handler::Error});
return [storage, taskId](const TaskObject &, bool success) {
storage->m_log.append({taskId, success ? Handler::Done : Handler::Error});
};
};
@@ -237,14 +233,13 @@ void tst_Tasking::testTree_data()
};
};
const auto createTask = [storage, setupTask, setupDone, setupError](
const auto createTask = [storage, setupTask, setupDone](
int taskId, bool successTask, milliseconds timeout = 0ms) -> GroupItem {
if (successTask)
return TestTask(setupTask(taskId, timeout), setupDone(taskId), setupError(taskId));
return TestTask(setupTask(taskId, timeout), setupDone(taskId));
const Group root {
finishAllAndError,
TestTask(setupTask(taskId, timeout)),
onGroupDone([storage, taskId] { storage->m_log.append({taskId, Handler::Done}); }),
onGroupError([storage, taskId] { storage->m_log.append({taskId, Handler::Error}); })
};
return root;
@@ -258,9 +253,9 @@ void tst_Tasking::testTree_data()
return createTask(taskId, false, timeout);
};
const auto createDynamicTask = [storage, setupDynamicTask, setupDone, setupError](
int taskId, SetupResult action) {
return TestTask(setupDynamicTask(taskId, action), setupDone(taskId), setupError(taskId));
const auto createDynamicTask = [storage, setupDynamicTask, setupDone](int taskId,
SetupResult action) {
return TestTask(setupDynamicTask(taskId, action), setupDone(taskId));
};
const auto groupSetup = [storage](int taskId) {
@@ -2121,7 +2116,7 @@ void tst_Tasking::testTree_data()
// 2. With and without timeout handler.
const Group root1 {
Storage(storage),
TestTask(setupTask(1, 1000ms), setupDone(1), setupError(1))
TestTask(setupTask(1, 1000ms), setupDone(1))
.withTimeout(1ms)
};
const Log log1 {
@@ -2133,7 +2128,7 @@ void tst_Tasking::testTree_data()
const Group root2 {
Storage(storage),
TestTask(setupTask(1, 1000ms), setupDone(1), setupError(1))
TestTask(setupTask(1, 1000ms), setupDone(1))
.withTimeout(1ms, setupTimeout(1))
};
const Log log2 {
@@ -2146,7 +2141,7 @@ void tst_Tasking::testTree_data()
const Group root3 {
Storage(storage),
TestTask(setupTask(1, 1ms), setupDone(1), setupError(1))
TestTask(setupTask(1, 1ms), setupDone(1))
.withTimeout(1000ms)
};
const Log doneLog {
@@ -2158,7 +2153,7 @@ void tst_Tasking::testTree_data()
const Group root4 {
Storage(storage),
TestTask(setupTask(1, 1ms), setupDone(1), setupError(1))
TestTask(setupTask(1, 1ms), setupDone(1))
.withTimeout(1000ms, setupTimeout(1))
};
QTest::newRow("TaskDoneWithTimeoutHandler") << TestData{storage, root4, doneLog, 2,