diff options
Diffstat (limited to 'src/concurrent/qtaskbuilder.h')
-rw-r--r-- | src/concurrent/qtaskbuilder.h | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/concurrent/qtaskbuilder.h b/src/concurrent/qtaskbuilder.h new file mode 100644 index 0000000000..95ab8021e7 --- /dev/null +++ b/src/concurrent/qtaskbuilder.h @@ -0,0 +1,135 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QTBASE_QTTASKBUILDER_H +#define QTBASE_QTTASKBUILDER_H + +#if !defined(QT_NO_CONCURRENT) || defined(Q_QDOC) + +#include <QtConcurrent/qtconcurrentstoredfunctioncall.h> + +QT_BEGIN_NAMESPACE + +#ifdef Q_QDOC + +namespace QtConcurrent { + +enum class FutureResult { Ignore }; + +using InvokeResultType = int; + +template <class Task, class ...Args> +class QTaskBuilder +{ +public: + [[nodiscard]] + QFuture<InvokeResultType> spawn(); + + void spawn(FutureResult); + + template <class ...ExtraArgs> + [[nodiscard]] + QTaskBuilder<Task, ExtraArgs...> withArguments(ExtraArgs &&...args); + + [[nodiscard]] + QTaskBuilder<Task, Args...> &onThreadPool(QThreadPool &newThreadPool); + + [[nodiscard]] + QTaskBuilder<Task, Args...> &withPriority(int newPriority); +}; + +} // namespace QtConcurrent + +#else + +namespace QtConcurrent { + +enum class FutureResult { Ignore }; + +template <class Task, class ...Args> +class QTaskBuilder +{ +public: + [[nodiscard]] + auto spawn() + { + return TaskResolver<std::decay_t<Task>, std::decay_t<Args>...>::run( + std::move(taskWithArgs), startParameters); + } + + // We don't want to run with promise when we don't return a QFuture + void spawn(FutureResult) + { + (new StoredFunctionCall<Task, Args...>(std::move(taskWithArgs))) + ->start(startParameters); + } + + template <class ...ExtraArgs> + [[nodiscard]] + constexpr auto withArguments(ExtraArgs &&...args) + { + static_assert(std::tuple_size_v<TaskWithArgs> == 1, + "This function cannot be invoked if " + "arguments have already been passed."); + + static_assert(sizeof...(ExtraArgs) >= 1, + "One or more arguments must be passed."); + + // We have to re-create a builder, because the type has changed + return QTaskBuilder<Task, ExtraArgs...>( + startParameters, + std::get<0>(std::move(taskWithArgs)), + std::forward<ExtraArgs>(args)... + ); + } + + [[nodiscard]] + constexpr auto &onThreadPool(QThreadPool &newThreadPool) + { + startParameters.threadPool = &newThreadPool; + return *this; + } + + [[nodiscard]] + constexpr auto &withPriority(int newPriority) + { + startParameters.priority = newPriority; + return *this; + } + +protected: // Methods + constexpr explicit QTaskBuilder(Task &&task, Args &&...arguments) + : taskWithArgs{std::forward<Task>(task), std::forward<Args>(arguments)...} + {} + + constexpr QTaskBuilder( + const TaskStartParameters ¶meters, Task &&task, Args &&...arguments) + : taskWithArgs{std::forward<Task>(task), std::forward<Args>(arguments)...} + , startParameters{parameters} + {} + +private: // Methods + // Required for creating a builder from "task" function + template <class T> + friend constexpr auto task(T &&t); + + // Required for creating a new builder from "withArguments" function + template <class T, class ...A> + friend class QTaskBuilder; + +private: // Data + using TaskWithArgs = DecayedTuple<Task, Args...>; + + TaskWithArgs taskWithArgs; + TaskStartParameters startParameters; +}; + +} // namespace QtConcurrent + +#endif // Q_QDOC + +QT_END_NAMESPACE + +#endif // !defined(QT_NO_CONCURRENT) + +#endif //QTBASE_QTTASKBUILDER_H |