IceShard 1
A personal game engine project, with development focused on 2D/2.5D games.
Loading...
Searching...
No Matches
task_generator.hxx
Go to the documentation of this file.
1
3
4#pragma once
5#include <ice/assert.hxx>
7
8namespace ice
9{
10
11 template<typename Value>
13 {
14 public:
15 inline auto initial_suspend() const noexcept -> std::suspend_never { return {}; }
16
17 inline auto get_return_object() noexcept -> ice::Generator<Value>;
18
19 template<typename Other = Value>
20 requires std::is_nothrow_move_assignable_v<Value> && std::is_nothrow_convertible_v<Other&&, Value>
21 inline auto yield_value(Other&& value) noexcept -> ice::suspend_always
22 {
23 _value = std::forward<Other>(value);
24 return {};
25 }
26
27 template<typename Other = Value>
28 requires std::is_nothrow_copy_assignable_v<Value> && std::is_nothrow_convertible_v<Other&&, Value>
29 inline auto yield_value(Other const& value) noexcept -> ice::suspend_always
30 {
31 _value = value;
32 return {};
33 }
34
35 inline auto result() & noexcept -> Value&
36 {
37 return _value;
38 }
39
40 inline auto result() && noexcept -> Value&&
41 {
42 return std::move(_value);
43 }
44
45 void return_void() noexcept
46 {
47 }
48
49 private:
50 Value _value;
51 };
52
53 template<typename Result>
54 class Generator final
55 {
56 public:
59
60 public:
61 inline explicit Generator(
63 ) noexcept;
64 inline ~Generator() noexcept;
65
66 inline Generator(Generator const&) noexcept = delete;
67 inline auto operator=(Generator const&) noexcept = delete;
68
69 inline Generator(Generator&&) noexcept;
70 inline auto operator=(Generator&& other) noexcept -> Generator&;
71
72 inline auto operator co_await() & noexcept;
73 inline auto operator co_await() && noexcept;
74
76 {
78
79 auto operator*() & noexcept -> Result& { return _coro.promise().result(); }
80 auto operator*() && noexcept -> Result&& { return ice::move(_coro.promise().result()); }
81
82 auto operator++() noexcept -> GeneratorIterator&
83 {
84 if (_coro.done() == false)
85 {
86 _coro.resume();
87 }
88 return *this;
89 }
90
91 bool operator==(GeneratorIterator const& other) const noexcept
92 {
93 return _coro == other._coro && _coro.done();
94 }
95
96 auto end() noexcept -> Result*
97 {
98 return nullptr;
99 }
100 };
101
102 auto begin() noexcept { return GeneratorIterator{ _coroutine }; }
103 auto end() noexcept { return GeneratorIterator{ _coroutine }; }
104
105 private:
106 struct AwaitableBase
107 {
109
110 inline bool await_ready() const noexcept;
111 inline auto await_suspend(
112 ice::coroutine_handle<> awaiting_coroutine
113 ) const noexcept -> ice::coroutine_handle<>;
114 };
115
116 private:
117 ice::coroutine_handle<PromiseType> _coroutine;
118 };
119
120 template<typename Result>
121 inline bool Generator<Result>::AwaitableBase::await_ready() const noexcept
122 {
123 return !_coroutine || _coroutine.done();
124 }
125
126 template<typename Result>
127 inline auto Generator<Result>::AwaitableBase::await_suspend(
128 ice::coroutine_handle<> awaiting_coroutine
129 ) const noexcept -> ice::coroutine_handle<>
130 {
131 _coroutine.promise().set_continuation(awaiting_coroutine);
132 return _coroutine;
133 }
134
135 template<typename Result>
137 : _coroutine{ coro }
138 { }
139
140 template<typename Result>
142 {
143 if (_coroutine)
144 {
145 _coroutine.destroy();
146 }
147 }
148
149 template<typename Result>
151 : _coroutine{ ice::exchange(other._coroutine, nullptr) }
152 { }
153
154 template<typename Result>
155 inline auto Generator<Result>::operator=(Generator&& other) noexcept -> Generator&
156 {
157 if (this != &other)
158 {
159 if (_coroutine != nullptr)
160 {
161 _coroutine.destroy();
162 }
163
164 _coroutine = ice::exchange(other._coroutine, nullptr);
165 }
166
167 return *this;
168 }
169
170 template<typename Result>
171 inline auto Generator<Result>::operator co_await() & noexcept
172 {
173 struct GeneratorAwaitable : AwaitableBase
174 {
175 auto await_resume() const noexcept -> decltype(auto)
176 {
178 this->_coroutine.operator bool(),
179 "Broken promise on coroutine Generator!"
180 );
181
182 if constexpr (std::is_same_v<ValueType, void> == false)
183 {
184 return this->_coroutine.promise().result();
185 }
186 }
187 };
188
189 return GeneratorAwaitable{ _coroutine };
190 }
191
192 template<typename Result>
193 inline auto Generator<Result>::operator co_await() && noexcept
194 {
195 struct GeneratorAwaitable : AwaitableBase
196 {
197 auto await_resume() const noexcept -> decltype(auto)
198 {
200 this->_coroutine.operator bool(),
201 "Broken promise on coroutine Generator!"
202 );
203
204 if constexpr (std::is_same_v<ValueType, void> == false)
205 {
206 return ice::move(this->_coroutine.promise().result());
207 }
208 }
209 };
210
211 return GeneratorAwaitable{ ice::move(_coroutine) };
212 }
213
214 template<typename Value>
219
220} // namespace ice
221
222template<typename Result, typename... Args>
223struct std::coroutine_traits<ice::Generator<Result>, Args...>
224{
226};
#define ICE_ASSERT(condition, message,...)
Definition assert.hxx:29
Definition task_generator.hxx:55
Result ValueType
Definition task_generator.hxx:57
~Generator() noexcept
Definition task_generator.hxx:141
ice::GeneratorPromise< ValueType > PromiseType
Definition task_generator.hxx:58
auto begin() noexcept
Definition task_generator.hxx:102
auto end() noexcept
Definition task_generator.hxx:103
Generator(ice::coroutine_handle< PromiseType > coro=nullptr) noexcept
Definition task_generator.hxx:136
auto operator=(Generator const &) noexcept=delete
Definition task_generator.hxx:13
auto yield_value(Other const &value) noexcept -> ice::suspend_always
Definition task_generator.hxx:29
auto result() &noexcept -> Value &
Definition task_generator.hxx:35
auto initial_suspend() const noexcept -> std::suspend_never
Definition task_generator.hxx:15
auto get_return_object() noexcept -> ice::Generator< Value >
Definition task_generator.hxx:215
auto result() &&noexcept -> Value &&
Definition task_generator.hxx:40
auto yield_value(Other &&value) noexcept -> ice::suspend_always
Definition task_generator.hxx:21
void return_void() noexcept
Definition task_generator.hxx:45
SPDX-License-Identifier: MIT.
Definition array.hxx:12
std::coroutine_handle< Type > coroutine_handle
Definition task_types.hxx:42
std::suspend_always suspend_always
Definition task_types.hxx:43
ice::Expected< ice::ErrorCode > Result
Definition expected.hxx:197
std::suspend_never suspend_never
Definition task_types.hxx:44
Definition task_generator.hxx:76
auto operator++() noexcept -> GeneratorIterator &
Definition task_generator.hxx:82
auto operator*() &noexcept -> Result &
Definition task_generator.hxx:79
bool operator==(GeneratorIterator const &other) const noexcept
Definition task_generator.hxx:91
auto end() noexcept -> Result *
Definition task_generator.hxx:96
auto operator*() &&noexcept -> Result &&
Definition task_generator.hxx:80
ice::coroutine_handle< PromiseType > _coro
Definition task_generator.hxx:77
Definition task_promise_base.hxx:13
typename ice::Generator< Result >::PromiseType promise_type
Definition task_generator.hxx:225