IceShard 1
A personal game engine project, with development focused on 2D/2.5D games.
Loading...
Searching...
No Matches
task_expected.hxx
Go to the documentation of this file.
1
3
4#pragma once
6
7namespace ice
8{
9
10 template<typename Result, typename ErrorType>
11 struct TaskExpected final
12 {
13 public:
17
18 public:
19 TaskExpected(CoroutineType coro = nullptr) noexcept;
20 ~TaskExpected() noexcept;
21
22 inline TaskExpected(TaskExpected const&) noexcept = delete;
23 inline auto operator=(TaskExpected const&) noexcept = delete;
24
25 inline TaskExpected(TaskExpected&&) noexcept;
26 inline auto operator=(TaskExpected&& other) noexcept -> TaskExpected&;
27
30 inline auto valid() const noexcept;
31
33 inline auto result() & noexcept -> Result&;
34
36 inline auto result() && noexcept -> Result&&;
37
39 inline auto error() const noexcept -> ErrorType;
40
45 inline auto operator co_await() & noexcept;
46
51 inline auto operator co_await() && noexcept;
52
53 private:
54 struct AwaitableBase
55 {
56 CoroutineType _coroutine;
57 bool _continue_on_error;
58
59 inline AwaitableBase(CoroutineType coro, bool continue_on_error) noexcept;
60
61 inline bool await_ready() const noexcept;
62 inline auto await_suspend(
63 CoroutineType awaiting_coroutine
64 ) const noexcept -> ice::coroutine_handle<>;
65
66 template<typename ResultType>
67 inline auto await_suspend(
69 ) const noexcept -> ice::coroutine_handle<>;
70
71 inline auto await_suspend(
72 ice::coroutine_handle<> awaiting_coroutine
73 ) const noexcept -> ice::coroutine_handle<>;
74 };
75
76 private:
77 CoroutineType _coroutine;
78 };
79
80 template<typename Result, typename ErrorType>
81 inline TaskExpected<Result, ErrorType>::AwaitableBase::AwaitableBase(
82 CoroutineType coro,
83 bool continue_on_error
84 ) noexcept
85 : _coroutine{ coro }
86 , _continue_on_error{ continue_on_error }
87 {
88 }
89
90 template<typename Result, typename ErrorType>
91 inline bool TaskExpected<Result, ErrorType>::AwaitableBase::await_ready() const noexcept
92 {
93 return !_coroutine || _coroutine.done();
94 }
95
96 template<typename Result, typename ErrorType>
98 CoroutineType awaiting_coroutine
99 ) const noexcept -> ice::coroutine_handle<>
100 {
101 _coroutine.promise().set_continuation(awaiting_coroutine);
102 _coroutine.promise()._error_continuation = awaiting_coroutine.promise()._error_continuation;
103 _coroutine.promise()._error_pointer = awaiting_coroutine.promise()._error_pointer;
104 return _coroutine;
105 }
106
107 template<typename Result, typename ErrorType>
108 template<typename ResultType>
110 ice::coroutine_handle<TaskExpectedPromise<ResultType, ErrorType>> awaiting_coroutine
111 ) const noexcept -> ice::coroutine_handle<>
112 {
113 _coroutine.promise().set_continuation(awaiting_coroutine);
114 _coroutine.promise()._error_continuation = awaiting_coroutine.promise()._error_continuation;
115 _coroutine.promise()._error_pointer = awaiting_coroutine.promise()._error_pointer;
116 return _coroutine;
117 }
118
119 template<typename Result, typename ErrorType>
121 ice::coroutine_handle<> awaiting_coroutine
122 ) const noexcept -> ice::coroutine_handle<>
123 {
124 _coroutine.promise()._error_continuation = awaiting_coroutine; // Allows us to control if the coroutine should continue after failure.
125 _coroutine.promise().set_continuation(awaiting_coroutine);
126 return _coroutine;
127 }
128
129 template<typename Result, typename ErrorType>
131 : _coroutine{ coro }
132 { }
133
134 template<typename Result, typename ErrorType>
136 {
137 if (_coroutine)
138 {
139 _coroutine.destroy();
140 }
141 }
142
143 template<typename Result, typename ErrorType>
145 : _coroutine{ ice::exchange(other._coroutine, nullptr) }
146 { }
147
148 template<typename Result, typename ErrorType>
150 {
151 if (this != &other)
152 {
153 if (_coroutine != nullptr)
154 {
155 _coroutine.destroy();
156 }
157
158 _coroutine = ice::exchange(other._coroutine, nullptr);
159 }
160
161 return *this;
162 }
163
164 template<typename Result, typename ErrorType>
165 inline auto TaskExpected<Result, ErrorType>::valid() const noexcept
166 {
167 struct TaskAwaitable : AwaitableBase
168 {
169 using AwaitableBase::AwaitableBase;
170
171 auto await_ready() const noexcept
172 {
173 // Never continue if it was cancelled or failed already
174 return this->_coroutine.promise()._info->has_any(TaskState::Failed | TaskState::Canceled);
175 }
176
177 auto await_resume() const noexcept -> decltype(auto)
178 {
180 this->_coroutine.operator bool(),
181 "Broken promise on coroutine TaskExpected!"
182 );
183
184 return this->_coroutine.promise()._info->has_any(TaskState::Succeeded);
185 }
186 };
187
188 return TaskAwaitable{ _coroutine, true };
189 }
190
191 template<typename Result, typename ErrorType>
193 {
194 ICE_ASSERT_CORE(this->_coroutine && this->_coroutine.promise()._info->has_any(TaskState::Succeeded));
195 return this->_coroutine.promise().result();
196 }
197
198 template<typename Result, typename ErrorType>
199 inline auto TaskExpected<Result, ErrorType>::result() && noexcept -> Result&&
200 {
201 ICE_ASSERT_CORE(this->_coroutine && this->_coroutine.promise()._info->has_any(TaskState::Succeeded));
202 return ice::move(this->_coroutine.promise().result());
203 }
204
205 template<typename Result, typename ErrorType>
206 inline auto TaskExpected<Result, ErrorType>::error() const noexcept -> ErrorType
207 {
208 ICE_ASSERT_CORE(this->_coroutine != nullptr);
209 ice::TaskState const state = this->_coroutine.promise()._info->state;
210
212 if constexpr (std::is_same_v<ErrorType, ice::ErrorCode>)
213 {
215 {
216 return E_TaskCanceled;
217 }
218 }
219 else
220 {
222 }
223
224 return this->_coroutine.promise()._error_value;
225 }
226
227 template<typename Result, typename ErrorType>
228 inline auto TaskExpected<Result, ErrorType>::operator co_await() & noexcept
229 {
230 struct TaskAwaitable : AwaitableBase
231 {
232 using AwaitableBase::AwaitableBase;
233
234 auto await_resume() const noexcept -> decltype(auto)
235 {
237 this->_coroutine.operator bool(),
238 "Broken promise on coroutine TaskExpected!"
239 );
240
241 if constexpr (std::is_same_v<ValueType, void> == false)
242 {
243 return this->_coroutine.promise().expected();
244 }
245 }
246 };
247
248 return TaskAwaitable{ _coroutine, false };
249 }
250
251 template<typename Result, typename ErrorType>
252 inline auto TaskExpected<Result, ErrorType>::operator co_await() && noexcept
253 {
254 struct TaskAwaitable : AwaitableBase
255 {
256 using AwaitableBase::AwaitableBase;
257
258 auto await_resume() const noexcept -> decltype(auto)
259 {
261 this->_coroutine.operator bool(),
262 "Broken promise on coroutine TaskExpected!"
263 );
264
265 if constexpr (std::is_same_v<ValueType, void> == false)
266 {
267 return this->_coroutine.promise().expected_moved();
268 }
269 }
270 };
271
272 return TaskAwaitable{ ice::move(_coroutine), false };
273 }
274
275 template<typename Result, typename ErrorType>
280
281} // namespace ice
282
283template<typename Result, typename ErrorType, typename... Args>
284struct std::coroutine_traits<ice::TaskExpected<Result, ErrorType>, Args...>
285{
287};
#define ICE_ASSERT(condition, message,...)
Definition assert.hxx:29
#define ICE_ASSERT_CORE(expression)
Definition assert_core.hxx:43
SPDX-License-Identifier: MIT.
Definition array.hxx:12
TaskState
All states a task can be in.
Definition task_info.hxx:13
@ Canceled
Task was canceled at any point of it's lifetime.
Definition task_info.hxx:32
@ Succeeded
Task finished execution with a valid result.
Definition task_info.hxx:29
@ Failed
Task finished execution but results are invalid.
Definition task_info.hxx:35
static constexpr ice::ErrorCode E_TaskCanceled
Definition error_codes.hxx:22
constexpr bool has_any(T value, T expected_flags) noexcept
Definition enum_flags.hxx:83
std::coroutine_handle< Type > coroutine_handle
Definition task_types.hxx:42
constexpr bool has_none(T value, T expected_flags) noexcept
Definition enum_flags.hxx:89
ice::Expected< ice::ErrorCode > Result
Definition expected.hxx:197
Definition task_expected.hxx:12
~TaskExpected() noexcept
Definition task_expected.hxx:135
ice::coroutine_handle< PromiseType > CoroutineType
Definition task_expected.hxx:16
TaskExpected(CoroutineType coro=nullptr) noexcept
Definition task_expected.hxx:130
ice::TaskExpectedPromise< Result, ErrorType > PromiseType
Definition task_expected.hxx:15
auto valid() const noexcept
Definition task_expected.hxx:165
auto result() &noexcept -> Result &
Definition task_expected.hxx:192
auto operator=(TaskExpected const &) noexcept=delete
Result ValueType
Definition task_expected.hxx:14
auto error() const noexcept -> ErrorType
Definition task_expected.hxx:206
Definition task_expected_promise.hxx:17
auto get_return_object() noexcept -> ice::TaskExpected< Result, ErrorType >
Definition task_expected.hxx:276
typename ice::TaskExpected< Result, ErrorType >::PromiseType promise_type
Definition task_expected.hxx:286