HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
generator.hpp
1// Copyright Take Vos 2020-2022.
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 <concepts>
8#include <coroutine>
9#include <optional>
10#include <memory>
11#include <memory_resource>
12#include "arguments.hpp"
13#include "assert.hpp"
14
15namespace hi::inline v1 {
16
27template<typename T>
28class generator {
29public:
30 using value_type = T;
31
33 public:
34 generator get_return_object()
35 {
36 return generator{handle_type::from_promise(*this)};
37 }
38
39 value_type const &value()
40 {
41 return *_value;
42 }
43
44 static std::suspend_never initial_suspend() noexcept
45 {
46 return {};
47 }
48
49 static std::suspend_always final_suspend() noexcept
50 {
51 return {};
52 }
53
54 std::suspend_always yield_value(value_type const &value) noexcept
55 {
56 _value = value;
57 return {};
58 }
59
60 std::suspend_always yield_value(value_type &&value) noexcept
61 {
62 _value = std::move(value);
63 return {};
64 }
65
66 void return_void() noexcept {}
67
68 // Disallow co_await in generator coroutines.
69 void await_transform() = delete;
70
71 void unhandled_exception() noexcept
72 {
73 _exception = std::current_exception();
74 }
75
76 void rethrow()
77 {
78 if (auto ptr = std::exchange(_exception, nullptr)) {
80 }
81 }
82
83 private:
84 std::optional<value_type> _value = {};
85 std::exception_ptr _exception = nullptr;
86 };
87
88 using handle_type = std::coroutine_handle<promise_type>;
89
91 public:
92 value_proxy(value_type const &value) noexcept : _value(value) {}
93
94 value_type const &operator*() const noexcept
95 {
96 return _value;
97 }
98
99 private:
100 value_type _value;
101 };
102
106 public:
107 using difference_type = ptrdiff_t;
108 using value_type = std::decay_t<value_type>;
109 using pointer = value_type const *;
110 using reference = value_type const &;
112
113 explicit const_iterator(handle_type coroutine) : _coroutine{coroutine} {}
114
118 {
119 hi_axiom(not at_end());
120 _coroutine.resume();
121 _coroutine.promise().rethrow();
122 return *this;
123 }
124
125 value_proxy operator++(int)
126 {
127 auto tmp = value_proxy(**this);
128 hi_axiom(not at_end());
129 _coroutine.resume();
130 _coroutine.promise().rethrow();
131 return tmp;
132 }
133
137 {
138 hi_axiom(not at_end());
139 return _coroutine.promise().value();
140 }
141
142 pointer *operator->() const noexcept
143 {
144 hi_axiom(not at_end());
145 return std::addressof(_coroutine.promise().value());
146 }
147
148 [[nodiscard]] bool at_end() const noexcept
149 {
150 return not _coroutine or _coroutine.done();
151 }
152
155 [[nodiscard]] bool operator==(std::default_sentinel_t) const noexcept
156 {
157 return at_end();
158 }
159
160 private:
161 handle_type _coroutine;
162 };
163
164 explicit generator(handle_type coroutine) : _coroutine(coroutine) {}
165
166 generator() = default;
167 ~generator()
168 {
169 if (_coroutine) {
170 _coroutine.destroy();
171 }
172 }
173
174 generator(const generator &) = delete;
175 generator &operator=(const generator &) = delete;
176
177 generator(generator &&other) noexcept : _coroutine{std::exchange(other._coroutine, {})}
178 {
179 }
180
181 generator &operator=(generator &&other) noexcept
182 {
183 hi_return_on_self_assignment(other);
184 if (_coroutine) {
185 _coroutine.destroy();
186 }
187 _coroutine = std::exchange(other._coroutine, {});
188 return *this;
189 }
190
194 {
195 return const_iterator{_coroutine};
196 }
197
201 {
202 return const_iterator{_coroutine};
203 }
204
207 std::default_sentinel_t end() const
208 {
209 return {};
210 }
211
214 std::default_sentinel_t cend() const
215 {
216 return {};
217 }
218
219private:
220 handle_type _coroutine;
221};
222
223} // namespace hi::inline v1
Utilities to assert and bound check.
#define hi_axiom(expression)
Specify an axiom; an expression that is true.
Definition assert.hpp:133
This file includes functions for manipulating parameter-packs.
DOXYGEN BUG.
Definition algorithm.hpp:15
A return value for a generator-function.
Definition generator.hpp:28
std::default_sentinel_t end() const
Return a sentinel for the iterator.
Definition generator.hpp:207
const_iterator cbegin() const
Start the generator-function and return an iterator.
Definition generator.hpp:200
std::default_sentinel_t cend() const
Return a sentinel for the iterator.
Definition generator.hpp:214
const_iterator begin() const
Start the generator-function and return an iterator.
Definition generator.hpp:193
Definition generator.hpp:32
Definition generator.hpp:90
A forward iterator which iterates through values co_yieled by the generator-function.
Definition generator.hpp:105
const_iterator & operator++()
Resume the generator-function.
Definition generator.hpp:117
reference & operator*() const
Retrieve the value co_yielded by the generator-function.
Definition generator.hpp:136
bool operator==(std::default_sentinel_t) const noexcept
Check if the generator-function has finished.
Definition generator.hpp:155
Definition concepts.hpp:36
Definition concepts.hpp:39
T addressof(T... args)
T current_exception(T... args)
T move(T... args)
T rethrow_exception(T... args)