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
|
\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.
|
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,
|
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 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.
|
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
|
\sa CustomTask(), TaskSetupHandler, GroupDoneHandler
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -1056,7 +1059,7 @@ private:
|
|||||||
/*!
|
/*!
|
||||||
\typealias GroupItem::GroupDoneHandler
|
\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.
|
The \c GroupDoneHandler is an argument of the onGroupDone() element.
|
||||||
Any function with the above signature, when passed as a group done handler,
|
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 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.
|
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
|
\sa onGroupDone(), GroupSetupHandler, CustomTask::TaskDoneHandler
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -2436,7 +2443,7 @@ bool TaskTreePrivate::invokeDoneHandler(RuntimeTask *node, DoneWith doneWith)
|
|||||||
\section2 Task's Done Handler
|
\section2 Task's Done Handler
|
||||||
|
|
||||||
When a running task finishes, the task tree invokes an optionally provided 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
|
\code
|
||||||
const auto onSetup = [](QProcess &process) {
|
const auto onSetup = [](QProcess &process) {
|
||||||
|
@@ -350,15 +350,19 @@ private:
|
|||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static GroupDoneHandler wrapGroupDone(Handler &&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
|
// R, V, D stands for: Done[R]esult, [V]oid, [D]oneWith
|
||||||
static constexpr bool isRD = isInvocable<DoneResult, Handler, DoneWith>();
|
static constexpr bool isRD = isInvocable<DoneResult, Handler, DoneWith>();
|
||||||
static constexpr bool isR = isInvocable<DoneResult, Handler>();
|
static constexpr bool isR = isInvocable<DoneResult, Handler>();
|
||||||
static constexpr bool isVD = isInvocable<void, Handler, DoneWith>();
|
static constexpr bool isVD = isInvocable<void, Handler, DoneWith>();
|
||||||
static constexpr bool isV = isInvocable<void, Handler>();
|
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 "
|
"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) {
|
return [handler](DoneWith result) {
|
||||||
|
if constexpr (isDoneResultType)
|
||||||
|
return handler;
|
||||||
if constexpr (isRD)
|
if constexpr (isRD)
|
||||||
return std::invoke(handler, result);
|
return std::invoke(handler, result);
|
||||||
if constexpr (isR)
|
if constexpr (isR)
|
||||||
@@ -496,7 +500,8 @@ private:
|
|||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static InterfaceDoneHandler wrapDone(Handler &&handler) {
|
static InterfaceDoneHandler wrapDone(Handler &&handler) {
|
||||||
if constexpr (std::is_same_v<Handler, TaskDoneHandler>)
|
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
|
// 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 isRTD = isInvocable<DoneResult, Handler, const Task &, DoneWith>();
|
||||||
static constexpr bool isRT = isInvocable<DoneResult, Handler, const Task &>();
|
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 isVT = isInvocable<void, Handler, const Task &>();
|
||||||
static constexpr bool isVD = isInvocable<void, Handler, DoneWith>();
|
static constexpr bool isVD = isInvocable<void, Handler, DoneWith>();
|
||||||
static constexpr bool isV = isInvocable<void, Handler>();
|
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 &), "
|
"Task done handler needs to take (const Task &, DoneWith), (const Task &), "
|
||||||
"(DoneWith) or (void) as arguments and has to return void or DoneResult. "
|
"(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.");
|
"The passed handler doesn't fulfill these requirements.");
|
||||||
return [handler](const TaskInterface &taskInterface, DoneWith result) {
|
return [handler](const TaskInterface &taskInterface, DoneWith result) {
|
||||||
|
if constexpr (isDoneResultType)
|
||||||
|
return handler;
|
||||||
const Adapter &adapter = static_cast<const Adapter &>(taskInterface);
|
const Adapter &adapter = static_cast<const Adapter &>(taskInterface);
|
||||||
if constexpr (isRTD)
|
if constexpr (isRTD)
|
||||||
return std::invoke(handler, *adapter.task(), result);
|
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};
|
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.
|
// This test checks if storage shadowing works OK.
|
||||||
QTest::newRow("StorageShadowing") << storageShadowingData();
|
QTest::newRow("StorageShadowing") << storageShadowingData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static QtMessageHandler s_oldMessageHandler = nullptr;
|
static QtMessageHandler s_oldMessageHandler = nullptr;
|
||||||
static QStringList s_messages;
|
static QStringList s_messages;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user