Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
tasktree.h
Go to the documentation of this file.
1// Copyright (C) 2024 Jarek Kobus
2// Copyright (C) 2024 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef TASKING_TASKTREE_H
6#define TASKING_TASKTREE_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include "tasking_global.h"
20
21#include <QtCore/QList>
22#include <QtCore/QObject>
23
24#include <memory>
25
26QT_BEGIN_NAMESPACE
27template <class T>
28class QFuture;
29
30namespace Tasking {
31
33
34// WorkflowPolicy:
35// 1. When all children finished with success -> report success, otherwise:
36// a) Report error on first error and stop executing other children (including their subtree).
37// b) On first error - continue executing all children and report error afterwards.
38// 2. When all children finished with error -> report error, otherwise:
39// a) Report success on first success and stop executing other children (including their subtree).
40// b) On first success - continue executing all children and report success afterwards.
41// 3. Stops on first finished child. In sequential mode it will never run other children then the first one.
42// Useful only in parallel mode.
43// 4. Always run all children, let them finish, ignore their results and report success afterwards.
44// 5. Always run all children, let them finish, ignore their results and report error afterwards.
45
47{
48 StopOnError, // 1a - Reports error on first child error, otherwise success (if all children were success).
49 ContinueOnError, // 1b - The same, but children execution continues. Reports success when no children.
50 StopOnSuccess, // 2a - Reports success on first child success, otherwise error (if all children were error).
51 ContinueOnSuccess, // 2b - The same, but children execution continues. Reports error when no children.
52 StopOnSuccessOrError, // 3 - Stops on first finished child and report its result.
53 FinishAllAndSuccess, // 4 - Reports success after all children finished.
54 FinishAllAndError // 5 - Reports error after all children finished.
55};
56Q_ENUM_NS(WorkflowPolicy)
57
64Q_ENUM_NS(SetupResult)
65
66enum class DoneResult
67{
70};
71Q_ENUM_NS(DoneResult)
72
73enum class DoneWith
74{
78};
79Q_ENUM_NS(DoneWith)
80
87Q_ENUM_NS(CallDoneIf)
88
90
91class LoopData;
92class StorageData;
93class TaskTreePrivate;
94
96{
97 Q_OBJECT
98
99Q_SIGNALS:
101
102private:
103 template <typename Task, typename Deleter> friend class TaskAdapter;
104 friend class TaskTreePrivate;
105 TaskInterface() = default;
106#ifdef Q_QDOC
107protected:
108#endif
109 virtual void start() = 0;
110};
111
113{
114public:
115 using Condition = std::function<bool(int)>; // Takes iteration, called prior to each iteration.
116 using ValueGetter = std::function<const void *(int)>; // Takes iteration, returns ptr to ref.
117
118 int iteration() const;
119
120protected:
121 Loop(); // LoopForever
122 Loop(int count, const ValueGetter &valueGetter = {}); // LoopRepeat, LoopList
123 Loop(const Condition &condition); // LoopUntil
124
125 const void *valuePtr() const;
126
127private:
129 friend class TaskTreePrivate;
130 std::shared_ptr<LoopData> m_loopData;
131};
132
133class TASKING_EXPORT LoopForever final : public Loop
134{
135public:
137};
138
139class TASKING_EXPORT LoopRepeat final : public Loop
140{
141public:
142 LoopRepeat(int count) : Loop(count) {}
143};
144
145class TASKING_EXPORT LoopUntil final : public Loop
146{
147public:
148 LoopUntil(const Condition &condition) : Loop(condition) {}
149};
150
151template <typename T>
152class LoopList final : public Loop
153{
154public:
155 LoopList(const QList<T> &list) : Loop(list.size(), [list](int i) { return &list.at(i); }) {}
156 const T *operator->() const { return static_cast<const T *>(valuePtr()); }
157 const T &operator*() const { return *static_cast<const T *>(valuePtr()); }
158};
159
161{
162private:
163 using StorageConstructor = std::function<void *(void)>;
164 using StorageDestructor = std::function<void(void *)>;
165 using StorageHandler = std::function<void(void *)>;
166
167 StorageBase(const StorageConstructor &ctor, const StorageDestructor &dtor);
168
169 void *activeStorageVoid() const;
170
171 friend bool operator==(const StorageBase &first, const StorageBase &second)
172 { return first.m_storageData == second.m_storageData; }
173
174 friend bool operator!=(const StorageBase &first, const StorageBase &second)
175 { return first.m_storageData != second.m_storageData; }
176
177 friend size_t qHash(const StorageBase &storage, uint seed = 0)
178 { return size_t(storage.m_storageData.get()) ^ seed; }
179
180 std::shared_ptr<StorageData> m_storageData;
181
182 template <typename StorageStruct> friend class Storage;
184 friend class StorageData;
185 friend class RuntimeContainer;
186 friend class TaskTree;
187 friend class TaskTreePrivate;
188};
189
190template <typename StorageStruct>
191class Storage final : public StorageBase
192{
193public:
194 Storage() : StorageBase(Storage::ctor(), Storage::dtor()) {}
195 StorageStruct &operator*() const noexcept { return *activeStorage(); }
196 StorageStruct *operator->() const noexcept { return activeStorage(); }
197 StorageStruct *activeStorage() const {
198 return static_cast<StorageStruct *>(activeStorageVoid());
199 }
200
201private:
202 static StorageConstructor ctor() { return [] { return new StorageStruct(); }; }
203 static StorageDestructor dtor() {
204 return [](void *storage) { delete static_cast<StorageStruct *>(storage); };
205 }
206};
207
209{
210public:
211 // Called when group entered, after group's storages are created
213 // Called when group done, before group's storages are deleted
215
216 template <typename StorageStruct>
217 GroupItem(const Storage<StorageStruct> &storage)
218 : m_type(Type::Storage)
220
221 // TODO: Add tests.
222 GroupItem(const QList<GroupItem> &children) : m_type(Type::List) { addChildren(children); }
223 GroupItem(std::initializer_list<GroupItem> children) : m_type(Type::List) { addChildren(children); }
224
225protected:
226 GroupItem(const Loop &loop) : GroupItem(GroupData{{}, {}, {}, loop}) {}
227 // Internal, provided by CustomTask
229 // Called prior to task start, just after createHandler
231 // Called on task done, just before deleteLater
233
240
246
253
261
262 GroupItem() = default;
263 GroupItem(Type type) : m_type(type) { }
264 GroupItem(const GroupData &data)
265 : m_type(Type::GroupData)
266 , m_groupData(data) {}
267 GroupItem(const TaskHandler &handler)
268 : m_type(Type::TaskHandler)
270 void addChildren(const QList<GroupItem> &children);
271
272 static GroupItem groupHandler(const GroupHandler &handler) { return GroupItem({handler}); }
273
274 // Checks if Function may be invoked with Args and if Function's return type is Result.
275 template <typename Result, typename Function, typename ...Args,
276 typename DecayedFunction = std::decay_t<Function>>
277 static constexpr bool isInvocable()
278 {
279 // Note, that std::is_invocable_r_v doesn't check Result type properly.
280 if constexpr (std::is_invocable_r_v<Result, DecayedFunction, Args...>)
281 return std::is_same_v<Result, std::invoke_result_t<DecayedFunction, Args...>>;
282 return false;
283 }
284
285private:
286 friend class ContainerNode;
287 friend class For;
288 friend class TaskNode;
289 friend class TaskTreePrivate;
292 Type m_type = Type::Group;
293 QList<GroupItem> m_children;
294 GroupData m_groupData;
295 QList<StorageBase> m_storageList;
296 TaskHandler m_taskHandler;
297};
298
300{
301public:
302 ExecutableItem withTimeout(std::chrono::milliseconds timeout,
303 const std::function<void()> &handler = {}) const;
304 ExecutableItem withLog(const QString &logName) const;
305 template <typename SenderSignalPairGetter>
306 ExecutableItem withCancel(SenderSignalPairGetter &&getter) const
307 {
308 const auto connectWrapper = [getter](QObject *guard, const std::function<void()> &trigger) {
309 const auto senderSignalPair = getter();
310 QObject::connect(senderSignalPair.first, senderSignalPair.second, guard, [trigger] {
311 trigger();
312 }, static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::SingleShotConnection));
313 };
314 return withCancelImpl(connectWrapper);
315 }
316
317protected:
318 ExecutableItem() = default;
319 ExecutableItem(const TaskHandler &handler) : GroupItem(handler) {}
320
321private:
324 const ExecutableItem &second);
326 const ExecutableItem &second);
327 TASKING_EXPORT friend ExecutableItem operator&&(const ExecutableItem &item, DoneResult result);
328 TASKING_EXPORT friend ExecutableItem operator||(const ExecutableItem &item, DoneResult result);
329
330 ExecutableItem withCancelImpl(
331 const std::function<void(QObject *, const std::function<void()> &)> &connectWrapper) const;
332};
333
335{
336public:
337 Group(const QList<GroupItem> &children) { addChildren(children); }
338 Group(std::initializer_list<GroupItem> children) { addChildren(children); }
339
340 // GroupData related:
341 template <typename Handler>
342 static GroupItem onGroupSetup(Handler &&handler) {
343 return groupHandler({wrapGroupSetup(std::forward<Handler>(handler))});
344 }
345 template <typename Handler>
346 static GroupItem onGroupDone(Handler &&handler, CallDoneIf callDoneIf = CallDoneIf::SuccessOrError) {
347 return groupHandler({{}, wrapGroupDone(std::forward<Handler>(handler)), callDoneIf});
348 }
349
350private:
351 template <typename Handler>
352 static GroupSetupHandler wrapGroupSetup(Handler &&handler)
353 {
354 // R, V stands for: Setup[R]esult, [V]oid
355 static constexpr bool isR = isInvocable<SetupResult, Handler>();
356 static constexpr bool isV = isInvocable<void, Handler>();
357 static_assert(isR || isV,
358 "Group setup handler needs to take no arguments and has to return void or SetupResult. "
359 "The passed handler doesn't fulfill these requirements.");
360 return [handler] {
361 if constexpr (isR)
362 return std::invoke(handler);
363 std::invoke(handler);
365 };
366 }
367 template <typename Handler>
368 static GroupDoneHandler wrapGroupDone(Handler &&handler)
369 {
370 static constexpr bool isDoneResultType = std::is_same_v<Handler, DoneResult>;
371 // R, B, V, D stands for: Done[R]esult, [B]ool, [V]oid, [D]oneWith
372 static constexpr bool isRD = isInvocable<DoneResult, Handler, DoneWith>();
373 static constexpr bool isR = isInvocable<DoneResult, Handler>();
374 static constexpr bool isBD = isInvocable<bool, Handler, DoneWith>();
375 static constexpr bool isB = isInvocable<bool, Handler>();
376 static constexpr bool isVD = isInvocable<void, Handler, DoneWith>();
377 static constexpr bool isV = isInvocable<void, Handler>();
378 static_assert(isDoneResultType || isRD || isR || isBD || isB || isVD || isV,
379 "Group done handler needs to take (DoneWith) or (void) as an argument and has to "
380 "return void, bool or DoneResult. Alternatively, it may be of DoneResult type. "
381 "The passed handler doesn't fulfill these requirements.");
382 return [handler](DoneWith result) {
383 if constexpr (isDoneResultType)
384 return handler;
385 if constexpr (isRD)
386 return std::invoke(handler, result);
387 if constexpr (isR)
388 return std::invoke(handler);
389 if constexpr (isBD)
390 return toDoneResult(std::invoke(handler, result));
391 if constexpr (isB)
392 return toDoneResult(std::invoke(handler));
393 if constexpr (isVD)
394 std::invoke(handler, result);
395 else if constexpr (isV)
396 std::invoke(handler);
397 return toDoneResult(result == DoneWith::Success);
398 };
399 }
400};
401
402template <typename Handler>
403static GroupItem onGroupSetup(Handler &&handler)
404{
405 return Group::onGroupSetup(std::forward<Handler>(handler));
406}
407
408template <typename Handler>
409static GroupItem onGroupDone(Handler &&handler, CallDoneIf callDoneIf = CallDoneIf::SuccessOrError)
410{
411 return Group::onGroupDone(std::forward<Handler>(handler), callDoneIf);
412}
413
415{
416public:
417 // Default: 1 (sequential). 0 means unlimited (parallel).
418 GroupItem operator()(int limit) const;
419};
420
422{
423public:
424 // Default: WorkflowPolicy::StopOnError.
425 GroupItem operator()(WorkflowPolicy policy) const;
426};
427
430
434
442
446
448{
449public:
450 template <typename ...Args>
451 For(const Loop &loop, const Args &...args)
452 : Group(withLoop(loop, args...)) { }
453
454protected:
455 For(const Loop &loop, const QList<GroupItem> &children) : Group({loop, children}) {}
456 For(const Loop &loop, std::initializer_list<GroupItem> children) : Group({loop, children}) {}
457
458private:
459 template <typename ...Args>
460 QList<GroupItem> withLoop(const Loop &loop, const Args &...args) {
461 QList<GroupItem> children{GroupItem(loop)};
462 appendChildren(std::make_tuple(args...), &children);
463 return children;
464 }
465
466 template <typename Tuple, std::size_t N = 0>
467 void appendChildren(const Tuple &tuple, QList<GroupItem> *children) {
468 constexpr auto TupleSize = std::tuple_size_v<Tuple>;
469 if constexpr (TupleSize > 0) {
470 // static_assert(workflowPolicyCount<Tuple>() <= 1, "Too many workflow policies in one group.");
471 children->append(std::get<N>(tuple));
472 if constexpr (N + 1 < TupleSize)
473 appendChildren<Tuple, N + 1>(tuple, children);
474 }
475 }
476};
477
478class TASKING_EXPORT Forever final : public For
479{
480public:
481 Forever(const QList<GroupItem> &children) : For(LoopForever(), children) {}
482 Forever(std::initializer_list<GroupItem> children) : For(LoopForever(), children) {}
483};
484
485// Synchronous invocation. Similarly to Group - isn't counted as a task inside taskCount()
486class TASKING_EXPORT Sync final : public ExecutableItem
487{
488public:
489 template <typename Handler>
490 Sync(Handler &&handler) {
491 addChildren({ onGroupDone(wrapHandler(std::forward<Handler>(handler))) });
492 }
493
494private:
495 template <typename Handler>
496 static auto wrapHandler(Handler &&handler) {
497 // R, B, V stands for: Done[R]esult, [B]ool, [V]oid
498 static constexpr bool isR = isInvocable<DoneResult, Handler>();
499 static constexpr bool isB = isInvocable<bool, Handler>();
500 static constexpr bool isV = isInvocable<void, Handler>();
501 static_assert(isR || isB || isV,
502 "Sync handler needs to take no arguments and has to return void, bool or DoneResult. "
503 "The passed handler doesn't fulfill these requirements.");
504 return handler;
505 }
506};
507
508template <typename Task, typename Deleter = std::default_delete<Task>>
510{
511protected:
512 TaskAdapter() : m_task(new Task) {}
513 Task *task() { return m_task.get(); }
514 const Task *task() const { return m_task.get(); }
515
516private:
517 using TaskType = Task;
518 using DeleterType = Deleter;
519 template <typename Adapter> friend class CustomTask;
520 std::unique_ptr<Task, Deleter> m_task;
521};
522
523template <typename Adapter>
524class CustomTask final : public ExecutableItem
525{
526public:
527 using Task = typename Adapter::TaskType;
528 using Deleter = typename Adapter::DeleterType;
529 static_assert(std::is_base_of_v<TaskAdapter<Task, Deleter>, Adapter>,
530 "The Adapter type for the CustomTask<Adapter> needs to be derived from "
531 "TaskAdapter<Task>.");
534
535 template <typename SetupHandler = TaskSetupHandler, typename DoneHandler = TaskDoneHandler>
536 CustomTask(SetupHandler &&setup = TaskSetupHandler(), DoneHandler &&done = TaskDoneHandler(),
538 : ExecutableItem({&createAdapter, wrapSetup(std::forward<SetupHandler>(setup)),
539 wrapDone(std::forward<DoneHandler>(done)), callDoneIf})
540 {}
541
542private:
543 static Adapter *createAdapter() { return new Adapter; }
544
545 template <typename Handler>
546 static InterfaceSetupHandler wrapSetup(Handler &&handler) {
547 if constexpr (std::is_same_v<Handler, TaskSetupHandler>)
548 return {}; // When user passed {} for the setup handler.
549 // R, V stands for: Setup[R]esult, [V]oid
550 static constexpr bool isR = isInvocable<SetupResult, Handler, Task &>();
551 static constexpr bool isV = isInvocable<void, Handler, Task &>();
552 static_assert(isR || isV,
553 "Task setup handler needs to take (Task &) as an argument and has to return void or "
554 "SetupResult. The passed handler doesn't fulfill these requirements.");
555 return [handler](TaskInterface &taskInterface) {
556 Adapter &adapter = static_cast<Adapter &>(taskInterface);
557 if constexpr (isR)
558 return std::invoke(handler, *adapter.task());
559 std::invoke(handler, *adapter.task());
561 };
562 }
563
564 template <typename Handler>
565 static InterfaceDoneHandler wrapDone(Handler &&handler) {
566 if constexpr (std::is_same_v<Handler, TaskDoneHandler>)
567 return {}; // User passed {} for the done handler.
568 static constexpr bool isDoneResultType = std::is_same_v<Handler, DoneResult>;
569 // R, B, V, T, D stands for: Done[R]esult, [B]ool, [V]oid, [T]ask, [D]oneWith
570 static constexpr bool isRTD = isInvocable<DoneResult, Handler, const Task &, DoneWith>();
571 static constexpr bool isRT = isInvocable<DoneResult, Handler, const Task &>();
572 static constexpr bool isRD = isInvocable<DoneResult, Handler, DoneWith>();
573 static constexpr bool isR = isInvocable<DoneResult, Handler>();
574 static constexpr bool isBTD = isInvocable<bool, Handler, const Task &, DoneWith>();
575 static constexpr bool isBT = isInvocable<bool, Handler, const Task &>();
576 static constexpr bool isBD = isInvocable<bool, Handler, DoneWith>();
577 static constexpr bool isB = isInvocable<bool, Handler>();
578 static constexpr bool isVTD = isInvocable<void, Handler, const Task &, DoneWith>();
579 static constexpr bool isVT = isInvocable<void, Handler, const Task &>();
580 static constexpr bool isVD = isInvocable<void, Handler, DoneWith>();
581 static constexpr bool isV = isInvocable<void, Handler>();
582 static_assert(isDoneResultType || isRTD || isRT || isRD || isR
583 || isBTD || isBT || isBD || isB
584 || isVTD || isVT || isVD || isV,
585 "Task done handler needs to take (const Task &, DoneWith), (const Task &), "
586 "(DoneWith) or (void) as arguments and has to return void, bool or DoneResult. "
587 "Alternatively, it may be of DoneResult type. "
588 "The passed handler doesn't fulfill these requirements.");
589 return [handler](const TaskInterface &taskInterface, DoneWith result) {
590 if constexpr (isDoneResultType)
591 return handler;
592 const Adapter &adapter = static_cast<const Adapter &>(taskInterface);
593 if constexpr (isRTD)
594 return std::invoke(handler, *adapter.task(), result);
595 if constexpr (isRT)
596 return std::invoke(handler, *adapter.task());
597 if constexpr (isRD)
598 return std::invoke(handler, result);
599 if constexpr (isR)
600 return std::invoke(handler);
601 if constexpr (isBTD)
602 return toDoneResult(std::invoke(handler, *adapter.task(), result));
603 if constexpr (isBT)
604 return toDoneResult(std::invoke(handler, *adapter.task()));
605 if constexpr (isBD)
606 return toDoneResult(std::invoke(handler, result));
607 if constexpr (isB)
608 return toDoneResult(std::invoke(handler));
609 if constexpr (isVTD)
610 std::invoke(handler, *adapter.task(), result);
611 else if constexpr (isVT)
612 std::invoke(handler, *adapter.task());
613 else if constexpr (isVD)
614 std::invoke(handler, result);
615 else if constexpr (isV)
616 std::invoke(handler);
617 return toDoneResult(result == DoneWith::Success);
618 };
619 }
620};
621
622class TASKING_EXPORT TaskTree final : public QObject
623{
625
626public:
627 TaskTree();
628 TaskTree(const Group &recipe);
629 ~TaskTree();
630
631 void setRecipe(const Group &recipe);
632
633 void start();
634 void cancel();
635 bool isRunning() const;
636
637 // Helper methods. They execute a local event loop with ExcludeUserInputEvents.
638 // The passed future is used for listening to the cancel event.
639 // Don't use it in main thread. To be used in non-main threads or in auto tests.
641 DoneWith runBlocking(const QFuture<void> &future);
642 static DoneWith runBlocking(const Group &recipe,
643 std::chrono::milliseconds timeout = std::chrono::milliseconds::max());
644 static DoneWith runBlocking(const Group &recipe, const QFuture<void> &future,
645 std::chrono::milliseconds timeout = std::chrono::milliseconds::max());
646
647 int asyncCount() const;
648 int taskCount() const;
649 int progressMaximum() const { return taskCount(); }
650 int progressValue() const; // all finished / skipped / stopped tasks, groups itself excluded
651
652 template <typename StorageStruct, typename Handler>
653 void onStorageSetup(const Storage<StorageStruct> &storage, Handler &&handler) {
654 static_assert(std::is_invocable_v<std::decay_t<Handler>, StorageStruct &>,
655 "Storage setup handler needs to take (Storage &) as an argument. "
656 "The passed handler doesn't fulfill this requirement.");
657 setupStorageHandler(storage,
658 wrapHandler<StorageStruct>(std::forward<Handler>(handler)), {});
659 }
660 template <typename StorageStruct, typename Handler>
661 void onStorageDone(const Storage<StorageStruct> &storage, Handler &&handler) {
662 static_assert(std::is_invocable_v<std::decay_t<Handler>, const StorageStruct &>,
663 "Storage done handler needs to take (const Storage &) as an argument. "
664 "The passed handler doesn't fulfill this requirement.");
665 setupStorageHandler(storage, {},
666 wrapHandler<const StorageStruct>(std::forward<Handler>(handler)));
667 }
668
670 void started();
671 void done(DoneWith result);
672 void asyncCountChanged(int count);
673 void progressValueChanged(int value); // updated whenever task finished / skipped / stopped
674
675private:
676 void setupStorageHandler(const StorageBase &storage,
677 StorageBase::StorageHandler setupHandler,
678 StorageBase::StorageHandler doneHandler);
679 template <typename StorageStruct, typename Handler>
680 StorageBase::StorageHandler wrapHandler(Handler &&handler) {
681 return [handler](void *voidStruct) {
682 auto *storageStruct = static_cast<StorageStruct *>(voidStruct);
683 std::invoke(handler, *storageStruct);
684 };
685 }
686
688};
689
691{
692public:
694
695private:
696 void start() final;
697};
698
700{
701public:
704
705private:
706 void start() final;
707 std::optional<int> m_timerId;
708};
709
710using TaskTreeTask = CustomTask<TaskTreeTaskAdapter>;
711using TimeoutTask = CustomTask<TimeoutTaskAdapter>;
712
713} // namespace Tasking
714
715QT_END_NAMESPACE
716
717#endif // TASKING_TASKTREE_H
void setupDownload(NetworkQuery *query, const QString &progressText)
void setProgress(int progressValue, int progressMaximum, const QString &progressText)
void clearProgress(const QString &progressText)
void updateProgress(int progressValue, int progressMaximum)
std::unique_ptr< QNetworkAccessManager > m_manager
std::unique_ptr< QTemporaryDir > m_temporaryDir
void progressChanged(int progressValue, int progressMaximum, const QString &progressText)
void localDownloadDirChanged(const QUrl &url)
void setOfflineAssetsFilePath(const QUrl &offlineAssetsFilePath)
virtual QUrl resolvedUrl(const QUrl &url) const
void setJsonFileName(const QString &jsonFileName)
void jsonFileNameChanged(const QString &)
void downloadBaseChanged(const QUrl &)
void setPreferredLocalDownloadDir(const QUrl &localDir)
void offlineAssetsFilePathChanged(const QUrl &)
void setDownloadBase(const QUrl &downloadBase)
void setZipFileName(const QString &zipFileName)
void zipFileNameChanged(const QString &)
void preferredLocalDownloadDirChanged(const QUrl &url)
void start() final
This method is called by the running TaskTree for starting the Task instance.
void setThreadPool(QThreadPool *pool)
QFuture< ResultType > future() const
QList< ResultType > results() const
ResultType result() const
void setConcurrentCallData(Function &&function, Args &&...args)
CustomTask(SetupHandler &&setup=TaskSetupHandler(), DoneHandler &&done=TaskDoneHandler(), CallDoneIf callDoneIf=CallDoneIf::SuccessOrError)
\typealias Tasking::CustomTask::Task
Definition tasktree.h:536
\inheaderfile solutions/tasking/tasktree.h \inmodule TaskingSolution
Definition tasktree.h:300
ExecutableItem withTimeout(std::chrono::milliseconds timeout, const std::function< void()> &handler={}) const
Attaches TimeoutTask to a copy of this ExecutableItem, elapsing after timeout in milliseconds,...
ExecutableItem withLog(const QString &logName) const
Attaches a custom debug printout to a copy of this ExecutableItem, issued on task startup and after t...
ExecutableItem(const TaskHandler &handler)
Definition tasktree.h:319
ExecutableItem withCancel(SenderSignalPairGetter &&getter) const
Definition tasktree.h:306
For(const Loop &loop, const Args &...args)
Definition tasktree.h:451
For(const Loop &loop, const QList< GroupItem > &children)
Definition tasktree.h:455
For(const Loop &loop, std::initializer_list< GroupItem > children)
Definition tasktree.h:456
Forever(std::initializer_list< GroupItem > children)
Definition tasktree.h:482
Forever(const QList< GroupItem > &children)
Definition tasktree.h:481
\inheaderfile solutions/tasking/tasktree.h \inmodule TaskingSolution
Definition tasktree.h:209
GroupItem(const Loop &loop)
Definition tasktree.h:226
GroupItem(std::initializer_list< GroupItem > children)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition tasktree.h:223
GroupItem(const TaskHandler &handler)
Definition tasktree.h:267
void addChildren(const QList< GroupItem > &children)
GroupItem(const GroupData &data)
Definition tasktree.h:264
GroupItem(Type type)
Definition tasktree.h:263
GroupItem(const QList< GroupItem > &children)
Constructs a GroupItem element with a given list of items.
Definition tasktree.h:222
GroupItem(const Storage< StorageStruct > &storage)
Constructs a GroupItem element holding the storage object.
Definition tasktree.h:217
static GroupItem groupHandler(const GroupHandler &handler)
Definition tasktree.h:272
static constexpr bool isInvocable()
Definition tasktree.h:277
\inheaderfile solutions/tasking/tasktree.h \inmodule TaskingSolution
Definition tasktree.h:335
static GroupItem onGroupSetup(Handler &&handler)
Definition tasktree.h:342
static GroupItem onGroupDone(Handler &&handler, CallDoneIf callDoneIf=CallDoneIf::SuccessOrError)
Definition tasktree.h:346
Group(std::initializer_list< GroupItem > children)
Constructs a group from std::initializer_list given by children.
Definition tasktree.h:338
Group(const QList< GroupItem > &children)
Constructs a group with a given list of children.
Definition tasktree.h:337
const T & operator*() const
Definition tasktree.h:157
LoopList(const QList< T > &list)
Definition tasktree.h:155
const T * operator->() const
Definition tasktree.h:156
LoopRepeat(int count)
Definition tasktree.h:142
LoopUntil(const Condition &condition)
Definition tasktree.h:148
Loop(int count, const ValueGetter &valueGetter={})
Loop(const Condition &condition)
int iteration() const
const void * valuePtr() const
GroupItem operator()(int limit) const
Constructs a group's element describing the \l{Execution Mode}{execution mode}.
friend bool operator==(const StorageBase &first, const StorageBase &second)
Definition tasktree.h:171
friend size_t qHash(const StorageBase &storage, uint seed=0)
Definition tasktree.h:177
friend class Storage
Definition tasktree.h:182
friend bool operator!=(const StorageBase &first, const StorageBase &second)
Definition tasktree.h:174
StorageStruct * operator->() const noexcept
Returns a pointer to the active StorageStruct object, created by the running task tree.
Definition tasktree.h:196
StorageStruct & operator*() const noexcept
Returns a reference to the active StorageStruct object, created by the running task tree.
Definition tasktree.h:195
Storage()
Creates a storage for the given StorageStruct type.
Definition tasktree.h:194
StorageStruct * activeStorage() const
Returns a pointer to the active StorageStruct object, created by the running task tree.
Definition tasktree.h:197
Sync(Handler &&handler)
Constructs an element that executes a passed handler synchronously.
Definition tasktree.h:490
\inheaderfile solutions/tasking/tasktree.h \inmodule TaskingSolution
Definition tasktree.h:510
const Task * task() const
Definition tasktree.h:514
friend class CustomTask
Definition tasktree.h:519
\inheaderfile solutions/tasking/tasktree.h \inmodule TaskingSolution
Definition tasktree.h:96
virtual void start()=0
This method is called by the running TaskTree for starting the Task instance.
void start() final
This method is called by the running TaskTree for starting the Task instance.
void done(DoneWith result)
This signal is emitted when the task tree finished, passing the final result of the execution.
DoneWith runBlocking(const QFuture< void > &future)
int progressMaximum() const
Returns the maximum progressValue().
Definition tasktree.h:649
TaskTree()
Constructs an empty task tree.
int taskCount() const
Returns the number of asynchronous tasks contained in the stored recipe.
void cancel()
Cancels the execution of the running task tree.
void start()
Starts the task tree.
void onStorageSetup(const Storage< StorageStruct > &storage, Handler &&handler)
Installs a storage setup handler for the storage to pass the initial data dynamically to the running ...
Definition tasktree.h:653
~TaskTree()
Destroys the task tree.
bool isRunning() const
Returns true if the task tree is currently running; otherwise returns false.
void onStorageDone(const Storage< StorageStruct > &storage, Handler &&handler)
Installs a storage done handler for the storage to retrieve the final data dynamically from the runni...
Definition tasktree.h:661
void setRecipe(const Group &recipe)
Sets a given recipe for the task tree.
void asyncCountChanged(int count)
This signal is emitted when the running task tree is about to return control to the caller's event lo...
static DoneWith runBlocking(const Group &recipe, const QFuture< void > &future, std::chrono::milliseconds timeout=std::chrono::milliseconds::max())
TaskTree(const Group &recipe)
This is an overloaded member function, provided for convenience. It differs from the above function o...
int progressValue() const
Returns the current progress value, which is between the 0 and progressMaximum().
DoneWith runBlocking()
Executes a local event loop with QEventLoop::ExcludeUserInputEvents and starts the task tree.
static DoneWith runBlocking(const Group &recipe, std::chrono::milliseconds timeout=std::chrono::milliseconds::max())
void progressValueChanged(int value)
This signal is emitted when the running task tree finished, canceled, or skipped some tasks.
int asyncCount() const
Returns the current real count of asynchronous chains of invocations.
void start() final
This method is called by the running TaskTree for starting the Task instance.
GroupItem operator()(WorkflowPolicy policy) const
Constructs a group's \l {Workflow Policy} {workflow policy} element for a given policy.
static void unzip(QPromise< void > &promise, const QByteArray &content, const QDir &directory, const QString &fileName)
static bool sameFileContent(const QFileInfo &first, const QFileInfo &second)
static void writeAsset(QPromise< void > &promise, const QByteArray &content, const QString &filePath)
static void precheckLocalFile(const QUrl &url)
static QDir baseLocalDir(const QDir &preferredLocalDir)
static QString pathFromUrl(const QUrl &url)
static bool allAssetsPresent(const QList< QUrl > &assetFiles, const QDir &expectedDir)
static void copyAndCheck(QPromise< void > &promise, const QString &sourcePath, const QString &destPath)
static bool canBeALocalBaseDir(const QDir &dir)
static QList< QUrl > filterDownloadableAssets(const QList< QUrl > &assetFiles, const QDir &expectedDir)
static void readAssetsFileContent(QPromise< DownloadableAssets > &promise, const QByteArray &content)
static bool createDirectory(const QDir &dir)
static bool isWritableDir(const QDir &dir)
Combined button and popup list for selecting options.
\inmodule TaskingSolution
const ExecutableItem successItem
SetupResult
Definition tasktree.h:59
WorkflowPolicy
Definition tasktree.h:47
const GroupItem sequential
const GroupItem continueOnSuccess
const GroupItem stopOnError
const GroupItem finishAllAndError
ExecutableItem operator&&(const ExecutableItem &first, const ExecutableItem &second)
const ExecutableItem errorItem
const ParallelLimitFunctor parallelLimit
ExecutableItem operator||(const ExecutableItem &item, DoneResult result)
const GroupItem finishAllAndSuccess
ExecutableItem operator!(const ExecutableItem &item)
DoneResult toDoneResult(bool success)
const GroupItem parallelIdealThreadCountLimit
ExecutableItem operator||(const ExecutableItem &first, const ExecutableItem &second)
const GroupItem stopOnSuccessOrError
ExecutableItem operator&&(const ExecutableItem &item, DoneResult result)
const GroupItem nullItem
const GroupItem parallel
static GroupItem onGroupSetup(Handler &&handler)
\typealias Tasking::GroupItem::GroupSetupHandler
Definition tasktree.h:403
const GroupItem continueOnError
const WorkflowPolicyFunctor workflowPolicy
const GroupItem stopOnSuccess
static GroupItem onGroupDone(Handler &&handler, CallDoneIf callDoneIf=CallDoneIf::SuccessOrError)
Constructs a group's element holding the group done handler.
Definition tasktree.h:409
std::optional< WorkflowPolicy > m_workflowPolicy
Definition tasktree.h:250
std::optional< int > m_parallelLimit
Definition tasktree.h:249
std::optional< Loop > m_loop
Definition tasktree.h:251
GroupDoneHandler m_doneHandler
Definition tasktree.h:243
GroupSetupHandler m_setupHandler
Definition tasktree.h:242
InterfaceSetupHandler m_setupHandler
Definition tasktree.h:236
InterfaceCreateHandler m_createHandler
Definition tasktree.h:235
InterfaceDoneHandler m_doneHandler
Definition tasktree.h:237
#define TASKING_EXPORT