HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
async_task.hpp
1// Copyright Take Vos 2023.
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 "../macros.hpp"
8#include "progress.hpp"
9#include "task.hpp"
10#include "awaitable.hpp"
11#include "awaitable_timer_intf.hpp"
12#include <future>
13
14hi_export_module(hikogui.dispatch.async_task);
15
16hi_export namespace hi {
17inline namespace v1 {
18
24template<typename Func, typename... Args>
25[[nodiscard]] std::invoke_result_t<Func, Args...> async_task(Func func, Args... args) requires(is_invocable_task_v<Func, Args...>)
26{
27 return func(args...);
28}
29
36template<typename Func, typename... Args>
37[[nodiscard]] task<std::invoke_result_t<Func, Args...>> async_task(Func func, Args... args)
38 requires(not is_invocable_task_v<Func, Args...>)
39{
40 using namespace std::literals;
41
42 auto future = std::async(std::launch::async, [func = std::move(func), ... args = std::move(args)] {
43 return func(args...);
44 });
45
46 if (not future.valid()) {
47 throw std::future_error(std::future_errc::no_state);
48 }
49
50 while (true) {
51 switch (future.wait_for(0s)) {
52 case std::future_status::deferred:
53 // This shouldn't really happen, this will cause the GUI to block.
54 co_return future.get();
55
56 case std::future_status::ready:
57 co_return future.get();
58
59 case std::future_status::timeout:
60 co_await 15ms;
61 break;
62
63 default:
64 hi_no_default();
65 }
66 }
67}
68
74 none = 0,
75
78 stop = 1,
79
82 progress = 2,
83
87};
88
94template<typename Func, typename... Args>
96 // clang-format off
97 constexpr static cancel_features_type value =
98 std::is_invocable_v<Func, std::stop_token, ::hi::progress_token, Args...> ? cancel_features_type::stop_and_progress :
99 std::is_invocable_v<Func, ::hi::progress_token, Args...> ? cancel_features_type::progress :
100 std::is_invocable_v<Func, std::stop_token, Args...> ? cancel_features_type::stop :
102 // clang-format on
103};
104
107template<typename Func, typename... Args>
108constexpr auto cancel_features_v = cancel_features<Func, Args...>::value;
109
110
111template<typename ResultType, typename FuncType, typename... ArgTypes>
112concept compatible_cancelable_async_function_none = requires(FuncType f, ArgTypes... args) {
113 {
114 f(args...)
115 } -> std::same_as<ResultType>;
116};
117
118template<typename ResultType, typename FuncType, typename... ArgTypes>
119concept compatible_cancelable_async_function_stop = requires(FuncType f, std::stop_token st, ArgTypes... args) {
120 {
121 f(st, args...)
122 } -> std::same_as<ResultType>;
123};
124
125template<typename ResultType, typename FuncType, typename... ArgTypes>
126concept compatible_cancelable_async_function_progress = requires(FuncType f, progress_token pt, ArgTypes... args) {
127 {
128 f(pt, args...)
129 } -> std::same_as<ResultType>;
130};
131
132template<typename ResultType, typename FuncType, typename... ArgTypes>
134 requires(FuncType f, std::stop_token st, progress_token pt, ArgTypes... args) {
135 {
136 f(st, pt, args...)
137 } -> std::same_as<ResultType>;
138 };
139
140template<typename ResultType, typename FuncType, typename... ArgTypes>
141concept compatible_cancelable_async_task_none = requires(FuncType f, ArgTypes... args) {
142 {
143 f(args...)
144 } -> std::same_as<task<ResultType>>;
145};
146
147template<typename ResultType, typename FuncType, typename... ArgTypes>
148concept compatible_cancelable_async_task_stop = requires(FuncType f, std::stop_token st, ArgTypes... args) {
149 {
150 f(st, args...)
151 } -> std::same_as<task<ResultType>>;
152};
153
154template<typename ResultType, typename FuncType, typename... ArgTypes>
155concept compatible_cancelable_async_task_progress = requires(FuncType f, progress_token pt, ArgTypes... args) {
156 {
157 f(pt, args...)
158 } -> std::same_as<task<ResultType>>;
159};
160
161template<typename ResultType, typename FuncType, typename... ArgTypes>
163 requires(FuncType f, std::stop_token st, progress_token pt, ArgTypes... args) {
164 {
165 f(st, pt, args...)
166 } -> std::same_as<task<ResultType>>;
167 };
168
171// clang-format off
172template<typename ResultType, typename FuncType, typename... ArgTypes>
174 compatible_cancelable_async_function_none<ResultType, FuncType, ArgTypes...> or
175 compatible_cancelable_async_function_stop<ResultType, FuncType, ArgTypes...> or
176 compatible_cancelable_async_function_progress<ResultType, FuncType, ArgTypes...> or
177 compatible_cancelable_async_function_stop_and_progress<ResultType, FuncType, ArgTypes...> or
178 compatible_cancelable_async_task_none<ResultType, FuncType, ArgTypes...> or
179 compatible_cancelable_async_task_stop<ResultType, FuncType, ArgTypes...> or
180 compatible_cancelable_async_task_progress<ResultType, FuncType, ArgTypes...> or
181 compatible_cancelable_async_task_stop_and_progress<ResultType, FuncType, ArgTypes...>;
182// clang-format on
183
196template<typename Func, typename... Args>
197[[nodiscard]] auto cancelable_async_task(Func func, std::stop_token stop_token, ::hi::progress_token progress_token, Args... args)
198{
199 constexpr auto features = cancel_features_v<Func, Args...>;
200
201 if constexpr (features == cancel_features_type::stop_and_progress) {
202 return async_task(std::move(func), std::move(stop_token), std::move(progress_token), std::move(args)...);
203
204 } else if constexpr (features == cancel_features_type::progress) {
205 return async_task(std::move(func), std::move(progress_token), std::move(args)...);
206
207 } else if constexpr (features == cancel_features_type::stop) {
208 return async_task(std::move(func), std::move(stop_token), std::move(args)...);
209
210 } else if constexpr (features == cancel_features_type::none) {
211 return async_task(std::move(func), std::move(args)...);
212
213 } else {
214 hi_static_no_default();
215 }
216}
217
218} // namespace v1
219}
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.
@ stop_and_progress
The extra arguments are a std::stop_token, followed by a hi::progress_token.
@ progress
The extra argument is a hi::progress_token.
@ stop
The extra argument is a std::stop_token.
std::invoke_result_t< Func, Args... > async_task(Func func, Args... args)
Run a function asynchronously as a co-routine task.
Definition async_task.hpp:25
auto cancelable_async_task(Func func, std::stop_token stop_token, ::hi::progress_token progress_token, Args... args)
Run a function asynchronously as a co-routine task.
Definition async_task.hpp:197
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Type trait to retrieve the cancel feautes of a invokable.
Definition async_task.hpp:95
Token to pass to a function to report its progress.
Definition progress.hpp:23
A concept for a callable that may be use in cancelable_async_task().
Definition async_task.hpp:173
T async(T... args)
T move(T... args)