mirror of
https://github.com/Naios/continuable.git
synced 2026-01-01 03:12:12 +08:00
First working version of co_await using continuables!
This commit is contained in:
parent
baf47b129c
commit
434db0fc24
@ -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
|
||||
|
||||
@ -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>();
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user