Corium 1.1.0
High-Performance Zero-Heap C++20 MPSC Application Runtime
Loading...
Searching...
No Matches
Generator.hpp
Go to the documentation of this file.
1
7#pragma once
8
9#include <coroutine>
10#include <exception>
11#include <iterator>
12#include <utility>
13
15
16namespace corium::async {
17
23template <typename T, typename Allocator = HeapFrameAllocator>
24class Generator {
25public:
26 using ValueType = T;
27 using AllocatorType = Allocator;
28
29 struct promise_type {
30 const T* currentValue{nullptr};
31 std::exception_ptr exception{nullptr};
32
33 [[nodiscard]] static void* operator new(std::size_t size) {
34 return Allocator::allocate(size);
35 }
36
37 static void operator delete(void* ptr) noexcept {
38 Allocator::deallocate(ptr, 0);
39 }
40
41 static void operator delete(void* ptr, std::size_t size) noexcept {
42 Allocator::deallocate(ptr, size);
43 }
44
46 {
47 return Generator(std::coroutine_handle<promise_type>::from_promise(*this));
48 }
49
50 std::suspend_always initial_suspend() noexcept { return {}; }
51 std::suspend_always final_suspend() noexcept { return {}; }
52
53 std::suspend_always yield_value(const T& val) noexcept
54 {
55 currentValue = std::addressof(val);
56 return {};
57 }
58
59 std::suspend_always yield_value(T&& val) noexcept
60 {
61 currentValue = std::addressof(val);
62 return {};
63 }
64
65 void return_void() noexcept {}
66
67 void unhandled_exception() noexcept
68 {
69#if defined(__cpp_exceptions) || defined(__EXCEPTIONS)
70 exception = std::current_exception();
71#endif
72 }
73 };
74
75 class Sentinel {};
76
77 class Iterator {
78 public:
79 using iterator_category = std::input_iterator_tag;
80 using difference_type = std::ptrdiff_t;
81 using value_type = T;
82 using reference = const T&;
83 using pointer = const T*;
84
85 constexpr Iterator() noexcept = default;
86
87 explicit Iterator(std::coroutine_handle<promise_type> handle) noexcept
88 : _handle(handle)
89 {}
90
92 {
93 _handle.resume();
94 if (_handle.done()) {
95 if (_handle.promise().exception) {
96#if defined(__cpp_exceptions) || defined(__EXCEPTIONS)
97 std::rethrow_exception(_handle.promise().exception);
98#endif
99 }
100 }
101 return *this;
102 }
103
104 void operator++(int)
105 {
106 (void)operator++();
107 }
108
109 [[nodiscard]] reference operator*() const noexcept
110 {
111 return *_handle.promise().currentValue;
112 }
113
114 [[nodiscard]] pointer operator->() const noexcept
115 {
116 return _handle.promise().currentValue;
117 }
118
119 [[nodiscard]] bool operator==(Sentinel) const noexcept
120 {
121 return !_handle || _handle.done();
122 }
123
124 [[nodiscard]] bool operator!=(Sentinel s) const noexcept
125 {
126 return !(*this == s);
127 }
128
129 private:
130 std::coroutine_handle<promise_type> _handle{nullptr};
131 };
132
133 constexpr Generator() noexcept = default;
134
135 explicit Generator(std::coroutine_handle<promise_type> handle) noexcept
136 : _handle(handle)
137 {}
138
140 {
141 if (_handle) {
142 _handle.destroy();
143 }
144 }
145
146 Generator(const Generator&) = delete;
147 Generator& operator=(const Generator&) = delete;
148
149 Generator(Generator&& other) noexcept
150 : _handle(std::exchange(other._handle, nullptr))
151 {}
152
153 Generator& operator=(Generator&& other) noexcept
154 {
155 if (this != &other) {
156 if (_handle) {
157 _handle.destroy();
158 }
159 _handle = std::exchange(other._handle, nullptr);
160 }
161 return *this;
162 }
163
164 [[nodiscard]] Iterator begin()
165 {
166 if (_handle) {
167 _handle.resume();
168 if (_handle.promise().exception) {
169#if defined(__cpp_exceptions) || defined(__EXCEPTIONS)
170 std::rethrow_exception(_handle.promise().exception);
171#endif
172 }
173 }
174 return Iterator{_handle};
175 }
176
177 [[nodiscard]] constexpr Sentinel end() noexcept
178 {
179 return Sentinel{};
180 }
181
182private:
183 std::coroutine_handle<promise_type> _handle{nullptr};
184};
185
187template <typename T, std::size_t MaxFrames = 16, std::size_t FrameSize = 256>
189
190} // namespace corium::async
Zero-heap static coroutine frame pool and frame allocator policies.
Definition Generator.hpp:77
Iterator & operator++()
Definition Generator.hpp:91
T value_type
Definition Generator.hpp:81
void operator++(int)
Definition Generator.hpp:104
bool operator!=(Sentinel s) const noexcept
Definition Generator.hpp:124
constexpr Iterator() noexcept=default
std::ptrdiff_t difference_type
Definition Generator.hpp:80
const T * pointer
Definition Generator.hpp:83
reference operator*() const noexcept
Definition Generator.hpp:109
pointer operator->() const noexcept
Definition Generator.hpp:114
std::input_iterator_tag iterator_category
Definition Generator.hpp:79
const T & reference
Definition Generator.hpp:82
bool operator==(Sentinel) const noexcept
Definition Generator.hpp:119
Definition Generator.hpp:75
Zero-heap C++20 pull-based lazy generator sequence with configurable frame allocator....
Definition Generator.hpp:24
~Generator()
Definition Generator.hpp:139
Generator & operator=(const Generator &)=delete
Generator(Generator &&other) noexcept
Definition Generator.hpp:149
constexpr Sentinel end() noexcept
Definition Generator.hpp:177
T ValueType
Definition Generator.hpp:26
Allocator AllocatorType
Definition Generator.hpp:27
Iterator begin()
Definition Generator.hpp:164
Generator(const Generator &)=delete
Generator & operator=(Generator &&other) noexcept
Definition Generator.hpp:153
constexpr Generator() noexcept=default
Definition AsyncEvent.hpp:14
Definition Generator.hpp:29
void return_void() noexcept
Definition Generator.hpp:65
std::suspend_always final_suspend() noexcept
Definition Generator.hpp:51
void unhandled_exception() noexcept
Definition Generator.hpp:67
std::suspend_always initial_suspend() noexcept
Definition Generator.hpp:50
std::exception_ptr exception
Definition Generator.hpp:31
const T * currentValue
Definition Generator.hpp:30
std::suspend_always yield_value(const T &val) noexcept
Definition Generator.hpp:53
Generator get_return_object() noexcept
Definition Generator.hpp:45
std::suspend_always yield_value(T &&val) noexcept
Definition Generator.hpp:59