HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
coroutine.hpp
1// Copyright Take Vos 2020-2021.
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 <ranges>
8#include <concepts>
9#include <coroutine>
10
11namespace tt {
12
23template<typename T>
24class generator {
25public:
26 using value_type = T;
27
29 public:
30 generator<value_type> get_return_object()
31 {
32 return generator{handle_type::from_promise(*this)};
33 }
34
35 value_type const &value() {
36 return *_value;
37 }
38
39 static std::suspend_always initial_suspend() noexcept
40 {
41 return {};
42 }
43
44 static std::suspend_always final_suspend() noexcept
45 {
46 return {};
47 }
48
49 std::suspend_always yield_value(value_type const &value) noexcept
50 {
51 _value = value;
52 return {};
53 }
54
55 std::suspend_always yield_value(value_type &&value) noexcept
56 {
57 _value = std::move(value);
58 return {};
59 }
60
61 void return_void() noexcept {}
62
63 // Disallow co_await in generator coroutines.
64 void await_transform() = delete;
65
66 [[noreturn]] static void unhandled_exception()
67 {
68 throw;
69 }
70
71 private:
72 std::optional<value_type> _value;
73 };
74
75 using handle_type = std::coroutine_handle<promise_type>;
76
77 explicit generator(handle_type coroutine) : _coroutine(coroutine) {}
78
79 generator() = default;
81 {
82 if (_coroutine) {
83 _coroutine.destroy();
84 }
85 }
86
87 generator(const generator &) = delete;
88 generator &operator=(const generator &) = delete;
89
90 generator(generator &&other) noexcept : _coroutine{other._coroutine}
91 {
92 other._coroutine = {};
93 }
94
95 generator &operator=(generator &&other) noexcept
96 {
97 if (this != &other) {
98 if (_coroutine) {
99 _coroutine.destroy();
100 }
101 _coroutine = other._coroutine;
102 other._coroutine = {};
103 }
104 return *this;
105 }
106
109 class iterator {
110 public:
111 explicit iterator(handle_type coroutine) : _coroutine{coroutine} {}
112
116 {
117 _coroutine.resume();
118 return *this;
119 }
120
123 value_type const &operator*() const
124 {
125 return _coroutine.promise().value();
126 }
127
130 [[nodiscard]] bool operator==(std::default_sentinel_t) const
131 {
132 return !_coroutine || _coroutine.done();
133 }
134
135
136 private:
137 handle_type _coroutine;
138 };
139
143 {
144 if (_coroutine) {
145 _coroutine.resume();
146 }
147 return iterator{_coroutine};
148 }
149
152 std::default_sentinel_t end()
153 {
154 return {};
155 }
156
157private:
158 handle_type _coroutine;
159};
160
161} // namespace tt
162
A return value for a generator-function.
Definition coroutine.hpp:24
std::default_sentinel_t end()
Return a sentinal for the iterator.
Definition coroutine.hpp:152
iterator begin()
Start the generator-function and return an iterator.
Definition coroutine.hpp:142
Definition coroutine.hpp:28
A forward iterator which iterates through values co_yieled by the generator-function.
Definition coroutine.hpp:109
bool operator==(std::default_sentinel_t) const
Check if the generator-function has finished.
Definition coroutine.hpp:130
iterator & operator++()
Resume the generator-function.
Definition coroutine.hpp:115
value_type const & operator*() const
Retrieve the value co_yielded by the generator-function.
Definition coroutine.hpp:123
T move(T... args)