#pragma once | |||||
namespace resumef | |||||
{ | |||||
template<class _Ty> | |||||
struct awaitable_t | |||||
{ | |||||
using value_type = _Ty; | |||||
using state_type = state_t<value_type>; | |||||
using future_type = future_t<value_type>; | |||||
using lock_type = typename state_type::lock_type; | |||||
private: | |||||
mutable counted_ptr<state_type> _state = make_counted<state_type>(); | |||||
public: | |||||
awaitable_t() {} | |||||
awaitable_t(const awaitable_t&) = default; | |||||
awaitable_t(awaitable_t&&) = default; | |||||
awaitable_t& operator = (const awaitable_t&) = default; | |||||
awaitable_t& operator = (awaitable_t&&) = default; | |||||
void set_value(value_type value) const | |||||
{ | |||||
_state->set_value(std::move(value)); | |||||
_state = nullptr; | |||||
} | |||||
void set_exception(std::exception_ptr e) | |||||
{ | |||||
_state->set_exception(std::move(e)); | |||||
_state = nullptr; | |||||
} | |||||
future_type get_future() | |||||
{ | |||||
return future_type{ _state }; | |||||
} | |||||
}; | |||||
template<> | |||||
struct awaitable_t<void> | |||||
{ | |||||
using value_type = void; | |||||
using state_type = state_t<void>; | |||||
using future_type = future_t<void>; | |||||
using lock_type = typename state_type::lock_type; | |||||
mutable counted_ptr<state_type> _state = make_counted<state_type>(); | |||||
awaitable_t() {} | |||||
awaitable_t(const awaitable_t&) = default; | |||||
awaitable_t(awaitable_t&&) = default; | |||||
awaitable_t& operator = (const awaitable_t&) = default; | |||||
awaitable_t& operator = (awaitable_t&&) = default; | |||||
void set_value() const | |||||
{ | |||||
_state->set_value(); | |||||
_state = nullptr; | |||||
} | |||||
void set_exception(std::exception_ptr e) | |||||
{ | |||||
_state->set_exception(std::move(e)); | |||||
_state = nullptr; | |||||
} | |||||
future_type get_future() | |||||
{ | |||||
return future_type{ _state }; | |||||
} | |||||
}; | |||||
} |
#pragma once | |||||
#include "state.h" | |||||
namespace resumef | |||||
{ | |||||
template <typename _Ty> | |||||
struct promise_impl_t | |||||
{ | |||||
using value_type = _Ty; | |||||
using state_type = state_t<value_type>; | |||||
using promise_type = promise_t<value_type>; | |||||
using future_type = future_t<value_type>; | |||||
using lock_type = typename state_type::lock_type; | |||||
counted_ptr<state_type> _state = make_counted<state_type>(); | |||||
promise_impl_t() {} | |||||
promise_impl_t(promise_impl_t&& _Right) noexcept = default; | |||||
promise_impl_t& operator = (promise_impl_t&& _Right) noexcept = default; | |||||
promise_impl_t(const promise_impl_t&) = delete; | |||||
promise_impl_t & operator = (const promise_impl_t&) = delete; | |||||
auto initial_suspend() noexcept; | |||||
auto final_suspend() noexcept; | |||||
void set_exception(std::exception_ptr e); | |||||
future_type get_return_object(); | |||||
void cancellation_requested(); | |||||
}; | |||||
template<class _Ty> | |||||
struct promise_t : public promise_impl_t<_Ty> | |||||
{ | |||||
using promise_impl_t<_Ty>::_state; | |||||
void return_value(value_type val); | |||||
void yield_value(value_type val); | |||||
}; | |||||
template<> | |||||
struct promise_t<void> : public promise_impl_t<void> | |||||
{ | |||||
using promise_impl_t<void>::_state; | |||||
void return_void(); | |||||
void yield_value(); | |||||
}; | |||||
} | |||||
| |||||
#pragma once | |||||
#pragma once | |||||
namespace resumef | |||||
{ | |||||
struct suspend_on_initial | |||||
{ | |||||
counted_ptr<state_base_t> _state; | |||||
inline bool await_ready() noexcept | |||||
{ | |||||
return false; | |||||
} | |||||
inline void await_suspend(coroutine_handle<> handler) noexcept | |||||
{ | |||||
_state->set_handler(handler); | |||||
} | |||||
inline void await_resume() noexcept | |||||
{ | |||||
} | |||||
}; | |||||
template <typename _Ty> | |||||
inline auto promise_impl_t<_Ty>::initial_suspend() noexcept | |||||
{ | |||||
return suspend_on_initial{ _state.get() }; | |||||
} | |||||
template <typename _Ty> | |||||
inline auto promise_impl_t<_Ty>::final_suspend() noexcept | |||||
{ | |||||
_state->promise_final_suspend(); | |||||
return std::experimental::suspend_never{}; | |||||
} | |||||
template <typename _Ty> | |||||
inline void promise_impl_t<_Ty>::set_exception(std::exception_ptr e) | |||||
{ | |||||
_state->set_exception(std::move(e)); | |||||
} | |||||
template <typename _Ty> | |||||
inline future_t<_Ty> promise_impl_t<_Ty>::get_return_object() | |||||
{ | |||||
return { _state }; | |||||
} | |||||
template <typename _Ty> | |||||
inline void promise_impl_t<_Ty>::cancellation_requested() | |||||
{ | |||||
} | |||||
template<class _Ty> | |||||
inline void promise_t<_Ty>::return_value(value_type val) | |||||
{ | |||||
_state->set_value(std::move(val)); | |||||
} | |||||
template<class _Ty> | |||||
inline void promise_t<_Ty>::yield_value(value_type val) | |||||
{ | |||||
_state->set_value(std::move(val)); | |||||
} | |||||
inline void promise_t<void>::return_void() | |||||
{ | |||||
_state->set_value(); | |||||
} | |||||
inline void promise_t<void>::yield_value() | |||||
{ | |||||
_state->set_value(); | |||||
} | |||||
} | |||||
#pragma once | |||||
namespace resumef | |||||
{ | |||||
template<class _PromiseT, typename _Enable> | |||||
inline void state_base_t::future_await_suspend(coroutine_handle<_PromiseT> handler) | |||||
{ | |||||
scoped_lock<lock_type> __guard(this->_mtx); | |||||
_PromiseT& promise = handler.promise(); | |||||
state_base_t* parent_state = promise._state.get(); | |||||
this->_parent = parent_state; | |||||
scheduler_t* sch = parent_state->_scheduler; | |||||
sch->add_await(this, handler); | |||||
} | |||||
template<typename _Ty> | |||||
auto state_t<_Ty>::future_await_resume() -> value_type | |||||
{ | |||||
scoped_lock<lock_type> __guard(this->_mtx); | |||||
if (this->_exception) | |||||
std::rethrow_exception(std::move(this->_exception)); | |||||
return std::move(this->_value.value()); | |||||
} | |||||
template<typename _Ty> | |||||
void state_t<_Ty>::set_value(value_type val) | |||||
{ | |||||
scoped_lock<lock_type> __guard(this->_mtx); | |||||
this->_value = std::move(val); | |||||
if (this->_scheduler != nullptr) | |||||
this->_scheduler->add_ready(this); | |||||
} | |||||
} | |||||