10 using _Alloc_char = std::allocator<char>;
12 std::atomic<intptr_t> _count{0};
31 coroutine_handle<> _coro;
35 virtual void destroy_deallocate();
37 virtual void resume() = 0;
38 virtual bool has_handler()
const noexcept = 0;
45 coroutine_handle<> get_handler()
const
54 while (next !=
nullptr)
57 next = next->get_parent();
63 return get_root()->_scheduler;
73 virtual void destroy_deallocate()
override;
76 virtual void resume()
override;
77 virtual bool has_handler()
const noexcept
override;
79 bool switch_scheduler_await_suspend(
scheduler_t* sch);
81 void set_initial_suspend(coroutine_handle<> handler)
86 #if RESUMEF_INLINE_STATE
100 enum struct initor_type : uint8_t
106 enum struct result_type : uint8_t
117 coroutine_handle<> _initor;
119 #if RESUMEF_DEBUG_COUNTER
122 uint32_t _alloc_size = 0;
124 std::atomic<result_type> _has_value{ result_type::None };
126 initor_type _is_initor = initor_type::None;
127 static_assert(
sizeof(std::atomic<result_type>) == 1);
128 static_assert(
alignof(std::atomic<result_type>) == 1);
129 static_assert(
sizeof(
bool) == 1);
130 static_assert(
alignof(
bool) == 1);
131 static_assert(
sizeof(std::atomic<initor_type>) == 1);
132 static_assert(
alignof(std::atomic<initor_type>) == 1);
136 #if RESUMEF_DEBUG_COUNTER
137 _id = ++g_resumef_state_id;
139 _is_future = !awaitor;
142 virtual void destroy_deallocate()
override;
143 virtual void resume()
override;
144 virtual bool has_handler()
const noexcept
override;
145 virtual state_base_t* get_parent()
const noexcept
override;
147 inline bool is_ready()
const noexcept
149 #pragma warning(disable : 6326) //warning C6326: Potential comparison of a constant with another constant.
153 #if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
157 return 0 !=
reinterpret_cast<const std::atomic<uint16_t> &
>(_has_value).load(std::memory_order_acquire);
159 return _has_value.load(std::memory_order_acquire) != result_type::None || _is_future;
160 #pragma warning(default : 6326)
162 inline bool has_handler_skip_lock()
const noexcept
164 return (
bool)_coro || _is_initor != initor_type::None;
167 inline uint32_t get_alloc_size()
const noexcept
172 inline bool future_await_ready() noexcept
175 return _has_value.load(std::memory_order_acquire) != result_type::None;
177 template<
class _PromiseT,
typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>>
178 void future_await_suspend(coroutine_handle<_PromiseT> handler);
180 bool switch_scheduler_await_suspend(
scheduler_t* sch);
182 template<
class _PromiseT,
typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>>
183 void promise_initial_suspend(coroutine_handle<_PromiseT> handler);
184 template<
class _PromiseT,
typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>>
185 void promise_final_suspend(coroutine_handle<_PromiseT> handler);
187 #if RESUMEF_INLINE_STATE
189 static _Sty* _Construct(
void* _Ptr,
size_t _Size)
191 _Sty* st =
new(_Ptr) _Sty(
false);
192 st->_alloc_size =
static_cast<uint32_t
>(_Size);
198 static inline _Sty* _Alloc_state(
bool awaitor)
201 size_t _Size = _Align_size<_Sty>();
202 #if RESUMEF_DEBUG_COUNTER
203 std::cout <<
"state_future_t::alloc, size=" << _Size << std::endl;
205 char* _Ptr = _Al.allocate(_Size);
206 _Sty* st =
new(_Ptr) _Sty(awaitor);
207 st->_alloc_size =
static_cast<uint32_t
>(_Size);
216 template <
typename _Ty>
222 using value_type = _Ty;
228 switch (_has_value.load(std::memory_order_acquire))
230 case result_type::Value:
231 _value.~value_type();
233 case result_type::Exception:
234 _exception.~exception_ptr();
241 auto future_await_resume() -> value_type;
242 template<
class _PromiseT,
typename U,
typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>>
243 void promise_yield_value(_PromiseT* promise, U&& val);
245 void set_exception(std::exception_ptr e);
247 void set_value(U&& val);
250 inline void throw_exception(_Exp e)
252 set_exception(std::make_exception_ptr(std::move(e)));
257 std::exception_ptr _exception;
262 void set_value_internal(U&& val);
263 void set_exception_internal(std::exception_ptr e);
266 #ifndef DOXYGEN_SKIP_PROPERTY
267 template <
typename _Ty>
273 using value_type = _Ty;
274 using reference_type = _Ty&;
280 if (_has_value.load(std::memory_order_acquire) == result_type::Exception)
281 _exception.~exception_ptr();
284 auto future_await_resume()->reference_type;
285 template<
class _PromiseT,
typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>>
286 void promise_yield_value(_PromiseT* promise, reference_type val);
288 void set_exception(std::exception_ptr e);
289 void set_value(reference_type val);
292 inline void throw_exception(_Exp e)
294 set_exception(std::make_exception_ptr(std::move(e)));
299 std::exception_ptr _exception;
303 void set_value_internal(reference_type val);
304 void set_exception_internal(std::exception_ptr e);
308 struct state_t<void> final :
public state_future_t
310 friend state_future_t;
311 using state_future_t::lock_type;
313 explicit state_t(
bool awaitor) :state_future_t(awaitor) {}
315 void future_await_resume();
316 template<
class _PromiseT,
typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>>
317 void promise_yield_value(_PromiseT* promise);
319 void set_exception(std::exception_ptr e);
323 inline void throw_exception(_Exp e)
325 set_exception(std::make_exception_ptr(std::move(e)));
328 std::exception_ptr _exception;
330 #endif //DOXYGEN_SKIP_PROPERTY