forked from qt-creator/qt-creator
TaskTree: Make it possible to pass DoneResult as a done handler
This patch addresses the 38th point in the bugreport below. Add tests for it. Adapt docs and warning messages accordingly. Task-number: QTCREATORBUG-28741 Change-Id: I276d2d4c3a514147f67252dc5073d79fed94b9ff Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -677,7 +677,7 @@ private:
|
||||
/*!
|
||||
\typealias CustomTask::TaskDoneHandler
|
||||
|
||||
Type alias for \c std::function<DoneResult(const Task &, DoneWith)>.
|
||||
Type alias for \c std::function<DoneResult(const Task &, DoneWith)> or DoneResult.
|
||||
|
||||
The \c TaskDoneHandler is an optional argument of a custom task element's constructor.
|
||||
Any function with the above signature, when passed as a task done handler,
|
||||
@@ -702,6 +702,9 @@ private:
|
||||
the DoneWith argument. When the handler returns the DoneResult value,
|
||||
the task's final result may be tweaked inside the done handler's body by the returned value.
|
||||
|
||||
For a \c TaskDoneHandler of the DoneResult type, no additional handling is executed,
|
||||
and the task finishes unconditionally with the passed value of DoneResult.
|
||||
|
||||
\sa CustomTask(), TaskSetupHandler, GroupDoneHandler
|
||||
*/
|
||||
|
||||
@@ -1056,7 +1059,7 @@ private:
|
||||
/*!
|
||||
\typealias GroupItem::GroupDoneHandler
|
||||
|
||||
Type alias for \c std::function<DoneResult(DoneWith)>.
|
||||
Type alias for \c std::function<DoneResult(DoneWith)> or DoneResult.
|
||||
|
||||
The \c GroupDoneHandler is an argument of the onGroupDone() element.
|
||||
Any function with the above signature, when passed as a group done handler,
|
||||
@@ -1071,6 +1074,10 @@ private:
|
||||
the DoneWith argument. When the handler returns the DoneResult value,
|
||||
the group's final result may be tweaked inside the done handler's body by the returned value.
|
||||
|
||||
For a \c GroupDoneHandler of the DoneResult type, no additional handling is executed,
|
||||
and the group finishes unconditionally with the passed value of DoneResult,
|
||||
ignoring the group's workflow policy.
|
||||
|
||||
\sa onGroupDone(), GroupSetupHandler, CustomTask::TaskDoneHandler
|
||||
*/
|
||||
|
||||
@@ -2436,7 +2443,7 @@ bool TaskTreePrivate::invokeDoneHandler(RuntimeTask *node, DoneWith doneWith)
|
||||
\section2 Task's Done Handler
|
||||
|
||||
When a running task finishes, the task tree invokes an optionally provided done handler.
|
||||
The handler should always take a \c const \e reference to the associated task class object:
|
||||
The handler should take a \c const \e reference to the associated task class object:
|
||||
|
||||
\code
|
||||
const auto onSetup = [](QProcess &process) {
|
||||
|
@@ -350,15 +350,19 @@ private:
|
||||
template <typename Handler>
|
||||
static GroupDoneHandler wrapGroupDone(Handler &&handler)
|
||||
{
|
||||
static constexpr bool isDoneResultType = std::is_same_v<Handler, DoneResult>;
|
||||
// R, V, D stands for: Done[R]esult, [V]oid, [D]oneWith
|
||||
static constexpr bool isRD = isInvocable<DoneResult, Handler, DoneWith>();
|
||||
static constexpr bool isR = isInvocable<DoneResult, Handler>();
|
||||
static constexpr bool isVD = isInvocable<void, Handler, DoneWith>();
|
||||
static constexpr bool isV = isInvocable<void, Handler>();
|
||||
static_assert(isRD || isR || isVD || isV,
|
||||
static_assert(isDoneResultType || isRD || isR || isVD || isV,
|
||||
"Group done handler needs to take (DoneWith) or (void) as an argument and has to "
|
||||
"return void or DoneResult. The passed handler doesn't fulfill these requirements.");
|
||||
"return void or DoneResult. Alternatively, it may be of DoneResult type. "
|
||||
"The passed handler doesn't fulfill these requirements.");
|
||||
return [handler](DoneWith result) {
|
||||
if constexpr (isDoneResultType)
|
||||
return handler;
|
||||
if constexpr (isRD)
|
||||
return std::invoke(handler, result);
|
||||
if constexpr (isR)
|
||||
@@ -496,7 +500,8 @@ private:
|
||||
template <typename Handler>
|
||||
static InterfaceDoneHandler wrapDone(Handler &&handler) {
|
||||
if constexpr (std::is_same_v<Handler, TaskDoneHandler>)
|
||||
return {}; // When user passed {} for the done handler.
|
||||
return {}; // User passed {} for the done handler.
|
||||
static constexpr bool isDoneResultType = std::is_same_v<Handler, DoneResult>;
|
||||
// R, V, T, D stands for: Done[R]esult, [V]oid, [T]ask, [D]oneWith
|
||||
static constexpr bool isRTD = isInvocable<DoneResult, Handler, const Task &, DoneWith>();
|
||||
static constexpr bool isRT = isInvocable<DoneResult, Handler, const Task &>();
|
||||
@@ -506,11 +511,14 @@ private:
|
||||
static constexpr bool isVT = isInvocable<void, Handler, const Task &>();
|
||||
static constexpr bool isVD = isInvocable<void, Handler, DoneWith>();
|
||||
static constexpr bool isV = isInvocable<void, Handler>();
|
||||
static_assert(isRTD || isRT || isRD || isR || isVTD || isVT || isVD || isV,
|
||||
static_assert(isDoneResultType || isRTD || isRT || isRD || isR || isVTD || isVT || isVD || isV,
|
||||
"Task done handler needs to take (const Task &, DoneWith), (const Task &), "
|
||||
"(DoneWith) or (void) as arguments and has to return void or DoneResult. "
|
||||
"Alternatively, it may be of DoneResult type. "
|
||||
"The passed handler doesn't fulfill these requirements.");
|
||||
return [handler](const TaskInterface &taskInterface, DoneWith result) {
|
||||
if constexpr (isDoneResultType)
|
||||
return handler;
|
||||
const Adapter &adapter = static_cast<const Adapter &>(taskInterface);
|
||||
if constexpr (isRTD)
|
||||
return std::invoke(handler, *adapter.task(), result);
|
||||
|
@@ -3174,11 +3174,49 @@ void tst_Tasking::testTree_data()
|
||||
QTest::newRow("ParallelDisorder") << TestData{storage, root, log, 2, DoneWith::Error, 1};
|
||||
}
|
||||
|
||||
{
|
||||
// This tests ensures the task done handler or onGroupDone accepts the DoneResult as an
|
||||
// argument.
|
||||
|
||||
const Group groupSuccess {
|
||||
storage,
|
||||
Group {
|
||||
onGroupDone(DoneResult::Success)
|
||||
},
|
||||
groupDone(0)
|
||||
};
|
||||
const Group groupError {
|
||||
storage,
|
||||
Group {
|
||||
onGroupDone(DoneResult::Error)
|
||||
},
|
||||
groupDone(0)
|
||||
};
|
||||
const Group taskSuccess {
|
||||
storage,
|
||||
TestTask({}, DoneResult::Success),
|
||||
groupDone(0)
|
||||
};
|
||||
const Group taskError {
|
||||
storage,
|
||||
TestTask({}, DoneResult::Error),
|
||||
groupDone(0)
|
||||
};
|
||||
|
||||
QTest::newRow("DoneResultGroupSuccess")
|
||||
<< TestData{storage, groupSuccess, {{0, Handler::GroupSuccess}}, 0, DoneWith::Success, 0};
|
||||
QTest::newRow("DoneResultGroupError")
|
||||
<< TestData{storage, groupError, {{0, Handler::GroupError}}, 0, DoneWith::Error, 0};
|
||||
QTest::newRow("DoneResultTaskSuccess")
|
||||
<< TestData{storage, taskSuccess, {{0, Handler::GroupSuccess}}, 1, DoneWith::Success, 1};
|
||||
QTest::newRow("DoneResultTaskError")
|
||||
<< TestData{storage, taskError, {{0, Handler::GroupError}}, 1, DoneWith::Error, 1};
|
||||
}
|
||||
|
||||
// This test checks if storage shadowing works OK.
|
||||
QTest::newRow("StorageShadowing") << storageShadowingData();
|
||||
}
|
||||
|
||||
|
||||
static QtMessageHandler s_oldMessageHandler = nullptr;
|
||||
static QStringList s_messages;
|
||||
|
||||
|
Reference in New Issue
Block a user