@@ -0,0 +1,75 @@ | |||
#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 }; | |||
} | |||
}; | |||
} |
@@ -0,0 +1,49 @@ | |||
#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(); | |||
}; | |||
} | |||
@@ -0,0 +1,80 @@ | |||
| |||
#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(); | |||
} | |||
} | |||
@@ -0,0 +1,37 @@ | |||
#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); | |||
} | |||
} | |||