librf

generator.h
1 /*
2 * Modify from <experimental/generator_t.h>
3 * Purpose: Library support of coroutines. generator_t class
4 * http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0057r0.pdf
5 */
6 #pragma once
7
8 #pragma pack(push,_CRT_PACKING)
9 #pragma push_macro("new")
10 #undef new
11
12 namespace resumef
13 {
14 template <typename _Ty, typename promise_type>
15 struct generator_iterator;
16
17 #ifndef DOXYGEN_SKIP_PROPERTY
18
19 template<typename promise_type>
20 struct generator_iterator<void, promise_type>
21 {
22 typedef std::input_iterator_tag iterator_category;
23 typedef ptrdiff_t difference_type;
24
25 coroutine_handle<promise_type> _Coro;
26
27 generator_iterator(std::nullptr_t) : _Coro(nullptr)
28 {
29 }
30
31 generator_iterator(coroutine_handle<promise_type> _CoroArg) : _Coro(_CoroArg)
32 {
33 }
34
35 generator_iterator& operator++()
36 {
37 if (_Coro.done())
38 _Coro = nullptr;
39 else
40 _Coro.resume();
41 return *this;
42 }
43
44 void operator++(int)
45 {
46 // This postincrement operator meets the requirements of the Ranges TS
47 // InputIterator concept, but not those of Standard C++ InputIterator.
48 ++* this;
49 }
50
51 bool operator==(generator_iterator const& right_) const
52 {
53 return _Coro == right_._Coro;
54 }
55
56 bool operator!=(generator_iterator const& right_) const
57 {
58 return !(*this == right_);
59 }
60 };
61
62 template <typename promise_type>
63 struct generator_iterator<std::nullptr_t, promise_type> : public generator_iterator<void, promise_type>
64 {
65 generator_iterator(std::nullptr_t) : generator_iterator<void, promise_type>(nullptr)
66 {
67 }
68 generator_iterator(coroutine_handle<promise_type> _CoroArg) : generator_iterator<void, promise_type>(_CoroArg)
69 {
70 }
71 };
72
73 template <typename _Ty, typename promise_type>
74 struct generator_iterator : public generator_iterator<void, promise_type>
75 {
76 using value_type = _Ty;
77 using reference = _Ty const&;
78 using pointer = _Ty const*;
79
80 generator_iterator(std::nullptr_t) : generator_iterator<void, promise_type>(nullptr)
81 {
82 }
83 generator_iterator(coroutine_handle<promise_type> _CoroArg) : generator_iterator<void, promise_type>(_CoroArg)
84 {
85 }
86
87 reference operator*() const
88 {
89 return *this->_Coro.promise()._CurrentValue;
90 }
91
92 pointer operator->() const
93 {
94 return this->_Coro.promise()._CurrentValue;
95 }
96 };
97 #endif //DOXYGEN_SKIP_PROPERTY
98
102 template <typename _Ty, typename _Alloc>
103 struct generator_t
104 {
105 using value_type = _Ty;
106 using state_type = state_generator_t;
107
108 #ifndef DOXYGEN_SKIP_PROPERTY
109 struct promise_type
110 {
111 using value_type = _Ty;
112 using state_type = state_generator_t;
113 using future_type = generator_t<value_type>;
114
115 _Ty const* _CurrentValue;
116
117 promise_type()
118 {
119 get_state()->set_initial_suspend(coroutine_handle<promise_type>::from_promise(*this));
120 }
121 promise_type(promise_type&& _Right) noexcept = default;
122 promise_type& operator = (promise_type&& _Right) noexcept = default;
123 promise_type(const promise_type&) = default;
124 promise_type& operator = (const promise_type&) = default;
125
126 generator_t get_return_object()
127 {
128 return generator_t{ *this };
129 }
130
131 suspend_always initial_suspend() noexcept
132 {
133 return {};
134 }
135
136 suspend_always final_suspend() noexcept
137 {
138 return {};
139 }
140
141 suspend_always yield_value(_Ty const& _Value) noexcept
142 {
143 _CurrentValue = std::addressof(_Value);
144 return {};
145 }
146
147 //template<class = std::enable_if_t<!std::is_same_v<_Ty, void>, _Ty>>
148 void return_value(_Ty const& _Value) noexcept
149 {
150 _CurrentValue = std::addressof(_Value);
151 }
152 //template<class = std::enable_if_t<std::is_same_v<_Ty, void>, _Ty>>
153 void return_value() noexcept
154 {
155 _CurrentValue = nullptr;
156 }
157
158 void set_exception(std::exception_ptr e)
159 {
160 (void)e;
161 std::terminate();
162 }
163 #if defined(__clang__) || defined(__GNUC__)
164 void unhandled_exception()
165 {
166 std::terminate();
167 }
168 #endif
169
170 template <typename _Uty>
171 _Uty&& await_transform(_Uty&& _Whatever) noexcept
172 {
173 static_assert(std::is_same_v<_Uty, void>,
174 "co_await is not supported in coroutines of type std::experiemental::generator_t");
175 return std::forward<_Uty>(_Whatever);
176 }
177
178 state_type* get_state() noexcept
179 {
180 #if RESUMEF_INLINE_STATE
181 size_t _State_size = _Align_size<state_type>();
182 #if defined(__clang__)
183 auto h = coroutine_handle<promise_type>::from_promise(*this);
184 char* ptr = reinterpret_cast<char*>(h.address()) - _State_size;
185 return reinterpret_cast<state_type*>(ptr);
186 #elif defined(_MSC_VER)
187 char* ptr = reinterpret_cast<char*>(this) - _State_size;
188 return reinterpret_cast<state_type*>(ptr);
189 #else
190 #error "Unknown compiler"
191 #endif
192 #else
193 return _state.get();
194 #endif
195 }
196
197 using _Alloc_char = typename std::allocator_traits<_Alloc>::template rebind_alloc<char>;
198 static_assert(std::is_same_v<char*, typename std::allocator_traits<_Alloc_char>::pointer>,
199 "generator_t does not support allocators with fancy pointer types");
200 static_assert(std::allocator_traits<_Alloc_char>::is_always_equal::value,
201 "generator_t only supports stateless allocators");
202
203 void* operator new(size_t _Size)
204 {
205 _Alloc_char _Al;
206 #if RESUMEF_INLINE_STATE
207 size_t _State_size = _Align_size<state_type>();
208 assert(_Size >= sizeof(uint32_t) && _Size < (std::numeric_limits<uint32_t>::max)() - sizeof(_State_size));
209
210 char* ptr = _Al.allocate(_Size + _State_size);
211 char* _Rptr = ptr + _State_size;
212 #if RESUMEF_DEBUG_COUNTER
213 std::cout << " generator_promise::new, alloc size=" << (_Size + _State_size) << std::endl;
214 std::cout << " generator_promise::new, alloc ptr=" << (void*)ptr << std::endl;
215 std::cout << " generator_promise::new, return ptr=" << (void*)_Rptr << std::endl;
216 #endif
217
218 //在初始地址上构造state
219 {
220 state_type* st = state_type::_Construct(ptr);
221 st->lock();
222 }
223
224 return _Rptr;
225 #else
226 char* ptr = _Al.allocate(_Size);
227 #if RESUMEF_DEBUG_COUNTER
228 std::cout << " generator_promise::new, alloc size=" << _Size << std::endl;
229 std::cout << " generator_promise::new, alloc ptr=" << (void*)ptr << std::endl;
230 std::cout << " generator_promise::new, return ptr=" << (void*)ptr << std::endl;
231 #endif
232
233 return ptr;
234 #endif
235 }
236
237 void operator delete(void* _Ptr, size_t _Size)
238 {
239 #if RESUMEF_INLINE_STATE
240 size_t _State_size = _Align_size<state_type>();
241 assert(_Size >= sizeof(uint32_t) && _Size < (std::numeric_limits<uint32_t>::max)() - sizeof(_State_size));
242
243 *reinterpret_cast<uint32_t*>(_Ptr) = static_cast<uint32_t>(_Size + _State_size);
244
245 state_type* st = reinterpret_cast<state_type*>(static_cast<char*>(_Ptr) - _State_size);
246 st->unlock();
247 #else
248 _Alloc_char _Al;
249 return _Al.deallocate(reinterpret_cast<char *>(_Ptr), _Size);
250 #endif
251 }
252 #if !RESUMEF_INLINE_STATE
253 private:
254 counted_ptr<state_type> _state = state_generator_t::_Alloc_state();
255 #endif
256 };
257 #endif //DOXYGEN_SKIP_PROPERTY
258
259 using iterator = generator_iterator<_Ty, promise_type>;
260
261 iterator begin()
262 {
263 if (_Coro)
264 {
265 _Coro.resume();
266 if (_Coro.done())
267 return{ nullptr };
268 }
269 return { _Coro };
270 }
271
272 iterator end()
273 {
274 return{ nullptr };
275 }
276
277 explicit generator_t(promise_type& _Prom)
278 : _Coro(coroutine_handle<promise_type>::from_promise(_Prom))
279 {
280 }
281
282 generator_t() = default;
283
284 generator_t(generator_t const&) = delete;
285 generator_t& operator=(generator_t const&) = delete;
286
287 generator_t(generator_t&& right_) noexcept
288 : _Coro(right_._Coro)
289 {
290 right_._Coro = nullptr;
291 }
292
293 generator_t& operator=(generator_t&& right_) noexcept
294 {
295 if (this != std::addressof(right_)) {
296 _Coro = right_._Coro;
297 right_._Coro = nullptr;
298 }
299 return *this;
300 }
301
302 ~generator_t()
303 {
304 if (_Coro) {
305 _Coro.destroy();
306 }
307 }
308
309 state_type* detach_state()
310 {
311 auto t = _Coro;
312 _Coro = nullptr;
313 return t.promise().get_state();
314 }
315
316 private:
317 coroutine_handle<promise_type> _Coro = nullptr;
318 };
319
320 } // namespace resumef
321
322 #pragma pop_macro("new")
323 #pragma pack(pop)
resumef::counted_ptr< state_type >
resumef::state_generator_t
专用于generator_t<>的state类。
Definition: state.h:70
resumef::generator_t
专用于co_yield函数。
Definition: generator.h:103