From df5e3c587a045fbd3d50233ecdde0e06dccf35a3 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 26 Apr 2023 12:33:11 +0200 Subject: [PATCH] TaskTree: Enhance Sync's function Make it possible to pass a void returning function to the Sync constructor. In this case it's assumed that function returns true by default and finishes successfully. Add some helpful error messages when requirements for the passed function are not met. Change-Id: I8be75acd277d06e87db3c87a6eb96173aa9cd890 Reviewed-by: Qt CI Bot Reviewed-by: Marcus Tillmanns --- src/libs/utils/tasktree.h | 25 ++++- tests/auto/utils/tasktree/tst_tasktree.cpp | 107 +++++++++++++++++---- 2 files changed, 109 insertions(+), 23 deletions(-) diff --git a/src/libs/utils/tasktree.h b/src/libs/utils/tasktree.h index 8e9c0a6c17b..0c1b5e7a33d 100644 --- a/src/libs/utils/tasktree.h +++ b/src/libs/utils/tasktree.h @@ -306,11 +306,28 @@ public: // Synchronous invocation. Similarly to Group - isn't counted as a task inside taskCount() class QTCREATOR_UTILS_EXPORT Sync : public Group { + public: - using SynchronousMethod = std::function; - Sync(const SynchronousMethod &sync) - : Group({OnGroupSetup([sync] { return sync() ? TaskAction::StopWithDone - : TaskAction::StopWithError; })}) {} + template + Sync(Function &&function) : Group(init(std::forward(function))) {} + +private: + template + static QList init(Function &&function) { + constexpr bool isInvocable = std::is_invocable_v>; + static_assert(isInvocable, + "Sync element: The synchronous function can't take any arguments."); + constexpr bool isBool = std::is_same_v>>; + constexpr bool isVoid = std::is_same_v>>; + static_assert(isBool || isVoid, + "Sync element: The synchronous function has to return void or bool."); + if constexpr (isBool) { + return {OnGroupSetup([function] { return function() ? TaskAction::StopWithDone + : TaskAction::StopWithError; })}; + } + return {OnGroupSetup([function] { function(); return TaskAction::StopWithDone; })}; + }; + }; QTCREATOR_UTILS_EXPORT extern ParallelLimit sequential; diff --git a/tests/auto/utils/tasktree/tst_tasktree.cpp b/tests/auto/utils/tasktree/tst_tasktree.cpp index a360752fa36..c0bb7839ec3 100644 --- a/tests/auto/utils/tasktree/tst_tasktree.cpp +++ b/tests/auto/utils/tasktree/tst_tasktree.cpp @@ -122,6 +122,32 @@ void tst_TaskTree::validConstructs() OnGroupDone([] {}), OnGroupError([] {}) }; + + // When turning each of below blocks on, you should see the specific compiler error message. + +#if 0 + { + // "Sync element: The synchronous function has to return void or bool." + const auto setupSync = [] { return 3; }; + const Sync sync(setupSync); + } +#endif + +#if 0 + { + // "Sync element: The synchronous function can't take any arguments." + const auto setupSync = [](int) { }; + const Sync sync(setupSync); + } +#endif + +#if 0 + { + // "Sync element: The synchronous function can't take any arguments." + const auto setupSync = [](int) { return true; }; + const Sync sync(setupSync); + } +#endif } void tst_TaskTree::processTree_data() @@ -174,7 +200,10 @@ void tst_TaskTree::processTree_data() const auto groupError = [storage](int groupId) { return [=] { storage->m_log.append({groupId, Handler::GroupError}); }; }; - const auto setupSync = [storage](int syncId, bool success) { + const auto setupSync = [storage](int syncId) { + return [=] { storage->m_log.append({syncId, Handler::Sync}); }; + }; + const auto setupSyncWithReturn = [storage](int syncId, bool success) { return [=] { storage->m_log.append({syncId, Handler::Sync}); return success; }; }; @@ -997,11 +1026,11 @@ void tst_TaskTree::processTree_data() { const Group root { Storage(storage), - Sync(setupSync(1, true)), - Sync(setupSync(2, true)), - Sync(setupSync(3, true)), - Sync(setupSync(4, true)), - Sync(setupSync(5, true)) + Sync(setupSync(1)), + Sync(setupSync(2)), + Sync(setupSync(3)), + Sync(setupSync(4)), + Sync(setupSync(5)) }; const Log log { {1, Handler::Sync}, @@ -1014,15 +1043,35 @@ void tst_TaskTree::processTree_data() << TestData{storage, root, log, 0, OnStart::NotRunning, OnDone::Success}; } + { + const Group root { + Storage(storage), + Sync(setupSyncWithReturn(1, true)), + Sync(setupSyncWithReturn(2, true)), + Sync(setupSyncWithReturn(3, true)), + Sync(setupSyncWithReturn(4, true)), + Sync(setupSyncWithReturn(5, true)) + }; + const Log log { + {1, Handler::Sync}, + {2, Handler::Sync}, + {3, Handler::Sync}, + {4, Handler::Sync}, + {5, Handler::Sync} + }; + QTest::newRow("SyncWithReturn") + << TestData{storage, root, log, 0, OnStart::NotRunning, OnDone::Success}; + } + { const Group root { Storage(storage), parallel, - Sync(setupSync(1, true)), - Sync(setupSync(2, true)), - Sync(setupSync(3, true)), - Sync(setupSync(4, true)), - Sync(setupSync(5, true)) + Sync(setupSync(1)), + Sync(setupSync(2)), + Sync(setupSync(3)), + Sync(setupSync(4)), + Sync(setupSync(5)) }; const Log log { {1, Handler::Sync}, @@ -1039,11 +1088,11 @@ void tst_TaskTree::processTree_data() const Group root { Storage(storage), parallel, - Sync(setupSync(1, true)), - Sync(setupSync(2, true)), - Sync(setupSync(3, false)), - Sync(setupSync(4, true)), - Sync(setupSync(5, true)) + Sync(setupSync(1)), + Sync(setupSync(2)), + Sync(setupSyncWithReturn(3, false)), + Sync(setupSync(4)), + Sync(setupSync(5)) }; const Log log { {1, Handler::Sync}, @@ -1057,11 +1106,11 @@ void tst_TaskTree::processTree_data() { const Group root { Storage(storage), - Sync(setupSync(1, true)), + Sync(setupSync(1)), Process(setupProcess(2)), - Sync(setupSync(3, true)), + Sync(setupSync(3)), Process(setupProcess(4)), - Sync(setupSync(5, true)), + Sync(setupSync(5)), OnGroupDone(groupDone(0)) }; const Log log { @@ -1076,6 +1125,26 @@ void tst_TaskTree::processTree_data() << TestData{storage, root, log, 2, OnStart::Running, OnDone::Success}; } + { + const Group root { + Storage(storage), + Sync(setupSync(1)), + Process(setupProcess(2)), + Sync(setupSyncWithReturn(3, false)), + Process(setupProcess(4)), + Sync(setupSync(5)), + OnGroupError(groupError(0)) + }; + const Log log { + {1, Handler::Sync}, + {2, Handler::Setup}, + {3, Handler::Sync}, + {0, Handler::GroupError} + }; + QTest::newRow("SyncAndAsyncError") + << TestData{storage, root, log, 2, OnStart::Running, OnDone::Failure}; + } + { Condition condition;