8 #pragma pack(push,_CRT_PACKING)
9 #pragma push_macro("new")
14 template <
typename _Ty,
typename promise_type>
15 struct generator_iterator;
17 #ifndef DOXYGEN_SKIP_PROPERTY
19 template<
typename promise_type>
20 struct generator_iterator<void, promise_type>
22 typedef std::input_iterator_tag iterator_category;
23 typedef ptrdiff_t difference_type;
25 coroutine_handle<promise_type> _Coro;
27 generator_iterator(std::nullptr_t) : _Coro(nullptr)
31 generator_iterator(coroutine_handle<promise_type> _CoroArg) : _Coro(_CoroArg)
35 generator_iterator& operator++()
51 bool operator==(generator_iterator
const& right_)
const
53 return _Coro == right_._Coro;
56 bool operator!=(generator_iterator
const& right_)
const
58 return !(*
this == right_);
62 template <
typename promise_type>
63 struct generator_iterator<std::nullptr_t, promise_type> :
public generator_iterator<void, promise_type>
65 generator_iterator(std::nullptr_t) : generator_iterator<void, promise_type>(nullptr)
68 generator_iterator(coroutine_handle<promise_type> _CoroArg) : generator_iterator<void, promise_type>(_CoroArg)
73 template <
typename _Ty,
typename promise_type>
74 struct generator_iterator :
public generator_iterator<void, promise_type>
76 using value_type = _Ty;
77 using reference = _Ty
const&;
78 using pointer = _Ty
const*;
80 generator_iterator(std::nullptr_t) : generator_iterator<void, promise_type>(nullptr)
83 generator_iterator(coroutine_handle<promise_type> _CoroArg) : generator_iterator<void, promise_type>(_CoroArg)
87 reference operator*()
const
89 return *this->_Coro.promise()._CurrentValue;
92 pointer operator->()
const
94 return this->_Coro.promise()._CurrentValue;
97 #endif //DOXYGEN_SKIP_PROPERTY
102 template <
typename _Ty,
typename _Alloc>
105 using value_type = _Ty;
108 #ifndef DOXYGEN_SKIP_PROPERTY
111 using value_type = _Ty;
115 _Ty
const* _CurrentValue;
119 get_state()->set_initial_suspend(coroutine_handle<promise_type>::from_promise(*
this));
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;
131 suspend_always initial_suspend() noexcept
136 suspend_always final_suspend() noexcept
141 suspend_always yield_value(_Ty
const& _Value) noexcept
143 _CurrentValue = std::addressof(_Value);
148 void return_value(_Ty
const& _Value) noexcept
150 _CurrentValue = std::addressof(_Value);
153 void return_value() noexcept
155 _CurrentValue =
nullptr;
158 void set_exception(std::exception_ptr e)
164 void unhandled_exception()
170 template <
typename _Uty>
171 _Uty&& await_transform(_Uty&& _Whatever) noexcept
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);
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;
186 #elif defined(_MSC_VER)
187 char* ptr =
reinterpret_cast<char*
>(
this) - _State_size;
190 #error "Unknown compiler"
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");
203 void*
operator new(
size_t _Size)
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));
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;
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;
237 void operator delete(
void* _Ptr,
size_t _Size)
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));
243 *
reinterpret_cast<uint32_t*
>(_Ptr) =
static_cast<uint32_t
>(_Size + _State_size);
249 return _Al.deallocate(
reinterpret_cast<char *
>(_Ptr), _Size);
252 #if !RESUMEF_INLINE_STATE
257 #endif //DOXYGEN_SKIP_PROPERTY
259 using iterator = generator_iterator<_Ty, promise_type>;
278 : _Coro(coroutine_handle<promise_type>::from_promise(_Prom))
288 : _Coro(right_._Coro)
290 right_._Coro =
nullptr;
295 if (
this != std::addressof(right_)) {
296 _Coro = right_._Coro;
297 right_._Coro =
nullptr;
313 return t.promise().get_state();
317 coroutine_handle<promise_type> _Coro =
nullptr;
322 #pragma pop_macro("new")
325 #ifndef DOXYGEN_SKIP_PROPERTY
328 namespace experimental {
330 template <
typename _Ty,
typename _Alloc,
typename... Args>
331 struct coroutine_traits<resumef::generator_t<_Ty, _Alloc>, Args...>
338 #endif //DOXYGEN_SKIP_PROPERTY