First working version of co_await using continuables!

This commit is contained in:
Denis Blank 2017-12-26 03:33:44 +01:00
parent baf47b129c
commit 434db0fc24
3 changed files with 30 additions and 23 deletions

View File

@ -38,6 +38,7 @@
#include <experimental/coroutine>
#include <continuable/continuable-api.hpp>
#include <continuable/detail/base.hpp>
#include <continuable/detail/expected.hpp>
#include <continuable/detail/features.hpp>
#include <continuable/detail/traits.hpp>
@ -57,11 +58,11 @@ struct void_guard_tag {};
template <typename T>
struct result_trait;
template <>
struct result_trait<traits::identity<void>> {
struct result_trait<traits::identity<>> {
using expected = util::expected<void_guard_tag>;
static auto wrap() {
return expected(void_guard_tag{});
static constexpr void_guard_tag wrap() noexcept {
return {};
}
static void unwrap(expected&& e) {
assert(e.is_value());
@ -75,9 +76,8 @@ struct result_trait<traits::identity<T>> {
static auto wrap(T arg) {
return std::move(arg);
}
static void unwrap(expected&& e) {
static auto unwrap(expected&& e) {
assert(e.is_value());
(void)e;
return std::move(e.get_value());
}
};
@ -89,16 +89,15 @@ struct result_trait<traits::identity<First, Second, Rest...>> {
return std::make_tuple(std::move(first), std::move(second),
std::move(rest)...);
}
static void unwrap(expected&& e) {
static auto unwrap(expected&& e) {
assert(e.is_value());
(void)e;
return std::move(e.get_value());
}
};
template <typename Continuable>
using result_storage_of_t =
result_trait<decltype(hint_of(traits::identity_of<Continuable>()))>;
using result_trait_t =
result_trait<decltype(base::hint_of(traits::identity_of<Continuable>()))>;
} // namespace detail
/// We import the coroutine handle in our namespace
@ -108,7 +107,7 @@ using std::experimental::coroutine_handle;
/// for waiting on a continuable in a stackless coroutine.
template <typename Continuable>
class awaitable {
using trait_t = detail::result_trait<Continuable>;
using trait_t = detail::result_trait_t<Continuable>;
/// The continuable which is invoked upon suspension
Continuable continuable_;
@ -117,6 +116,10 @@ class awaitable {
typename trait_t::expected result_;
public:
explicit awaitable(Continuable&& continuable)
: continuable_(std::move(continuable)) {
}
/// Since continuables are evaluated lazily we are not
/// capable to say whether the resumption will be instantly.
bool await_ready() const noexcept {
@ -135,14 +138,15 @@ public:
.done();
}
/// Resume the coroutine represented by the handle
auto await_resume() noexcept(false) {
if (result_) {
// When the result was resolved return it
trait_t::unwrap(std::move(result_));
return trait_t::unwrap(std::move(result_));
}
#if defined(CONTINUABLE_WITH_EXCEPTIONS)
std::rethrow_exception(result_.get_error());
std::rethrow_exception(result_.get_exception());
#else // CONTINUABLE_WITH_EXCEPTIONS
// Returning error types in await isn't supported as of now
util::trap();
@ -153,12 +157,12 @@ private:
/// Resolve the continuation through the result
template <typename... Args>
void resolve(Args&&... args) {
// ...
result_.set_value(trait_t::wrap(std::forward<Args>(args)...));
}
/// Resolve the continuation through an error
void resolve(types::dispatch_error_tag, types::error_type error) {
// ...
result_.set_exception(std::move(error));
}
};
@ -166,7 +170,7 @@ private:
/// the C++ coroutine TS.
template <typename T>
auto create_awaiter(T&& continuable) {
return awaitable<std::decay_t<T>>{std::forward<T>(continuable)};
return awaitable<std::decay_t<T>>(std::forward<T>(continuable));
}
} // namespace awaiting
} // namespace detail

View File

@ -240,11 +240,11 @@ public:
assert(is_value());
return cast<T>();
}
T& get_exception() noexcept {
types::error_type& get_exception() noexcept {
assert(is_exception());
return cast<types::error_type>();
}
T const& get_exception() const noexcept {
types::error_type const& get_exception() const noexcept {
assert(is_exception());
return cast<types::error_type>();
}

View File

@ -51,11 +51,6 @@ struct coroutine_traits<void, T...> {
} // namespace experimental
} // namespace std
TYPED_TEST(single_dimension_tests, is_awaitable) {
{}
}
auto mk() {
return cti::make_continuable<void>([](auto&& promise) {
// ...
@ -66,7 +61,15 @@ auto mk() {
void teststhh() {
auto c = mk();
// co_await std::move(c);
co_await std::move(c);
co_return;
}
TYPED_TEST(single_dimension_tests, is_awaitable) {
teststhh();
}
#endif // CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE