HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
task_controller.hpp
1// Copyright Take Vos 2024.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "task.hpp"
8#include "async_task.hpp"
9#include "progress.hpp"
10#include "../macros.hpp"
11
12hi_export_module(hikogui.dispatch.async_controller);
13
14hi_export namespace hi {
15inline namespace v1 {
16namespace detail {
17
18template<typename ResultType>
20public:
21 using result_type = ResultType;
22
23 virtual ~task_controller_base() = default;
24
25 [[nodiscard]] constexpr virtual cancel_features_type features() const noexcept = 0;
26
27 virtual task<result_type> run(std::stop_token stop_token, hi::progress_token progress_token) = 0;
28};
29
30template<typename ResultType, typename FuncType, typename... ArgTypes>
31class task_controller_impl : public task_controller_base<ResultType> {
32public:
33 using result_type = ResultType;
34
35 template<typename Func, typename... Args>
36 task_controller_impl(Func&& func, Args&&... args) : _func(std::forward<Func>(func)), _args(std::forward<Args>(args)...)
37 {
38 }
39
40 [[nodiscard]] constexpr cancel_features_type features() const noexcept override
41 {
42 return cancel_features_v<FuncType, ArgTypes...>;
43 }
44
45 task<result_type> run(std::stop_token stop_token, hi::progress_token progress_token) override
46 {
47 return std::apply(
48 cancelable_async_task<FuncType, ArgTypes...>,
49 std::tuple_cat(std::tuple{_func, std::move(stop_token), std::move(progress_token)}, _args));
50 }
51
52private:
53 FuncType _func;
54 std::tuple<ArgTypes...> _args;
55};
56
57} // namespace detail
58
62
67template<typename ResultType>
69public:
72 using result_type = ResultType;
73 using callback_type = notifier<>::callback_type;
74
75 task_controller(task_controller const&) = delete;
77 task_controller& operator=(task_controller const&) = delete;
78 task_controller& operator=(task_controller&&) = delete;
79
81 {
83 }
84
87 task_controller() noexcept
88 {
89 _progress_cb = _progress_sink.subscribe([this] {
90 this->_notifier();
91 });
92 }
93
99 template<typename Func, typename... Args>
100 task_controller(Func&& func, Args&&... args) requires compatible_cancelable_async_callable<ResultType, Func, Args...>
102 {
103 _pimpl = std::make_shared<detail::task_controller_impl<result_type, std::decay_t<Func>, std::decay_t<Args>...>>(
104 std::forward<Func>(func), std::forward<Args>(args)...);
105 }
106
113 template<typename Func, typename... Args>
114 void set_function(Func&& func, Args&&... args) requires compatible_cancelable_async_callable<ResultType, Func, Args...>
115 {
116 reset();
117 _pimpl = std::make_shared<detail::task_controller_impl<result_type, std::decay_t<Func>, std::decay_t<Args>...>>(
118 std::forward<Func>(func), std::forward<Args>(args)...);
119 }
120
126 {
127 using namespace std::literals;
128
129 reset();
130 _pimpl = nullptr;
131 }
132
137 [[nodiscard]] cancel_features_type features() const noexcept
138 {
139 if (_pimpl) {
140 return _pimpl->features();
141 } else {
143 }
144 }
145
148 [[nodiscard]] bool runnable() const noexcept
149 {
150 return static_cast<bool>(_pimpl);
151 }
152
155 [[nodiscard]] bool started() const noexcept
156 {
157 if (not runnable()) {
158 return false;
159 }
160 return _task.started();
161 }
162
165 [[nodiscard]] bool running() const noexcept
166 {
167 if (not runnable()) {
168 return false;
169 }
170 return _task.running();
171 }
172
175 [[nodiscard]] bool done() const noexcept
176 {
177 if (not runnable()) {
178 return false;
179 }
180 return _task.done();
181 }
182
187 void reset()
188 {
189 if (running()) {
190 throw task_running_error("Task is running.");
191 }
192
193 _task = {};
194 _stop_source = {};
195 _progress_sink.reset();
196 }
197
200 void run()
201 {
202 reset();
203 _task = _pimpl->run(_stop_source.get_token(), _progress_sink.get_token());
204 }
205
211 bool request_stop() noexcept
212 {
213 return _stop_source.request_stop();
214 }
215
221 [[nodiscard]] float_t progress() const noexcept
222 {
223 return _progress_sink.value();
224 }
225
231 [[nodiscard]] result_type value() const requires(not std::same_as<result_type, void>)
232 {
233 return _task.value();
234 }
235
238 template<typename Callback>
239 hi::notifier<>::callback_type subscribe(Callback&& callback, callback_flags flags = callback_flags::synchronous)
240 {
241 return _notifier.subscribe(std::forward<Callback>(callback), flags);
242 }
243
244private:
246 std::stop_source _stop_source = {};
247 progress_sink _progress_sink = {};
248 progress_sink::callback_type _progress_cb = {};
249 task<result_type> _task = {};
250 hi::notifier<> _notifier = {};
251};
252
253} // namespace v1
254}
STL namespace.
The HikoGUI namespace.
Definition array_generic.hpp:20
constexpr auto cancel_features_v
The value of the hi::cancel_features<> type trait.
Definition async_task.hpp:108
cancel_features_type
Features of an invocable.
Definition async_task.hpp:71
@ none
This invocable does not have extra arguments.
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Definition callback.hpp:77
Token to pass to a function to report its progress.
Definition progress.hpp:23
progress_token get_token() const noexcept
Get a token to pass to a function.
Definition progress.hpp:59
constexpr float value() const noexcept
Get the current progress.
Definition progress.hpp:81
void reset()
Reset progress.
Definition progress.hpp:66
notifier ::callback_type subscribe(Callback &&callback, callback_flags flags=callback_flags::synchronous)
Subscribe a callback function to be called when progress is modified.
Definition progress.hpp:96
Definition task_controller.hpp:19
Definition task_controller.hpp:31
Definition task_controller.hpp:59
A task controller.
Definition task_controller.hpp:68
void set_function(Func &&func, Args &&... args)
Set the coroutine or function and its arguments.
Definition task_controller.hpp:114
void run()
Run the assigned coroutine or function with the previous given arguments.
Definition task_controller.hpp:200
hi::notifier ::callback_type subscribe(Callback &&callback, callback_flags flags=callback_flags::synchronous)
Register a callback to be called when a coroutine or function reports progress.
Definition task_controller.hpp:239
bool request_stop() noexcept
Request stop.
Definition task_controller.hpp:211
float_t progress() const noexcept
Get progress of a function.
Definition task_controller.hpp:221
void reset()
Reset the state of the function to not-started.
Definition task_controller.hpp:187
result_type value() const
Get the return value from the coroutine or function.
Definition task_controller.hpp:231
bool runnable() const noexcept
Check if a function is assigned.
Definition task_controller.hpp:148
ResultType result_type
The result type returned by a hi::task or function.
Definition task_controller.hpp:72
bool running() const noexcept
Check if the function is currently running.
Definition task_controller.hpp:165
void unset_function()
Remove the task, so that it can no longer be run.
Definition task_controller.hpp:125
bool started() const noexcept
Check if the function was started.
Definition task_controller.hpp:155
task_controller(Func &&func, Args &&... args)
Create a new task_controller with a assigned coroutine or function and its arguments.
Definition task_controller.hpp:100
bool done() const noexcept
Check if the function has completed.
Definition task_controller.hpp:175
cancel_features_type features() const noexcept
The features of the coroutine or function that was assigned.
Definition task_controller.hpp:137
task_controller() noexcept
Create a new task_controller.
Definition task_controller.hpp:87
A concept for a callable that may be use in cancelable_async_task().
Definition async_task.hpp:173
T move(T... args)
T tuple_cat(T... args)