mirror of
https://github.com/Naios/continuable.git
synced 2026-02-12 05:09:49 +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 <experimental/coroutine>
|
||||||
|
|
||||||
#include <continuable/continuable-api.hpp>
|
#include <continuable/continuable-api.hpp>
|
||||||
|
#include <continuable/detail/base.hpp>
|
||||||
#include <continuable/detail/expected.hpp>
|
#include <continuable/detail/expected.hpp>
|
||||||
#include <continuable/detail/features.hpp>
|
#include <continuable/detail/features.hpp>
|
||||||
#include <continuable/detail/traits.hpp>
|
#include <continuable/detail/traits.hpp>
|
||||||
@ -57,11 +58,11 @@ struct void_guard_tag {};
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct result_trait;
|
struct result_trait;
|
||||||
template <>
|
template <>
|
||||||
struct result_trait<traits::identity<void>> {
|
struct result_trait<traits::identity<>> {
|
||||||
using expected = util::expected<void_guard_tag>;
|
using expected = util::expected<void_guard_tag>;
|
||||||
|
|
||||||
static auto wrap() {
|
static constexpr void_guard_tag wrap() noexcept {
|
||||||
return expected(void_guard_tag{});
|
return {};
|
||||||
}
|
}
|
||||||
static void unwrap(expected&& e) {
|
static void unwrap(expected&& e) {
|
||||||
assert(e.is_value());
|
assert(e.is_value());
|
||||||
@ -75,9 +76,8 @@ struct result_trait<traits::identity<T>> {
|
|||||||
static auto wrap(T arg) {
|
static auto wrap(T arg) {
|
||||||
return std::move(arg);
|
return std::move(arg);
|
||||||
}
|
}
|
||||||
static void unwrap(expected&& e) {
|
static auto unwrap(expected&& e) {
|
||||||
assert(e.is_value());
|
assert(e.is_value());
|
||||||
(void)e;
|
|
||||||
return std::move(e.get_value());
|
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),
|
return std::make_tuple(std::move(first), std::move(second),
|
||||||
std::move(rest)...);
|
std::move(rest)...);
|
||||||
}
|
}
|
||||||
static void unwrap(expected&& e) {
|
static auto unwrap(expected&& e) {
|
||||||
assert(e.is_value());
|
assert(e.is_value());
|
||||||
(void)e;
|
|
||||||
return std::move(e.get_value());
|
return std::move(e.get_value());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Continuable>
|
template <typename Continuable>
|
||||||
using result_storage_of_t =
|
using result_trait_t =
|
||||||
result_trait<decltype(hint_of(traits::identity_of<Continuable>()))>;
|
result_trait<decltype(base::hint_of(traits::identity_of<Continuable>()))>;
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
/// We import the coroutine handle in our namespace
|
/// 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.
|
/// for waiting on a continuable in a stackless coroutine.
|
||||||
template <typename Continuable>
|
template <typename Continuable>
|
||||||
class awaitable {
|
class awaitable {
|
||||||
using trait_t = detail::result_trait<Continuable>;
|
using trait_t = detail::result_trait_t<Continuable>;
|
||||||
|
|
||||||
/// The continuable which is invoked upon suspension
|
/// The continuable which is invoked upon suspension
|
||||||
Continuable continuable_;
|
Continuable continuable_;
|
||||||
@ -117,6 +116,10 @@ class awaitable {
|
|||||||
typename trait_t::expected result_;
|
typename trait_t::expected result_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
explicit awaitable(Continuable&& continuable)
|
||||||
|
: continuable_(std::move(continuable)) {
|
||||||
|
}
|
||||||
|
|
||||||
/// Since continuables are evaluated lazily we are not
|
/// Since continuables are evaluated lazily we are not
|
||||||
/// capable to say whether the resumption will be instantly.
|
/// capable to say whether the resumption will be instantly.
|
||||||
bool await_ready() const noexcept {
|
bool await_ready() const noexcept {
|
||||||
@ -135,14 +138,15 @@ public:
|
|||||||
.done();
|
.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resume the coroutine represented by the handle
|
||||||
auto await_resume() noexcept(false) {
|
auto await_resume() noexcept(false) {
|
||||||
if (result_) {
|
if (result_) {
|
||||||
// When the result was resolved return it
|
// 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)
|
#if defined(CONTINUABLE_WITH_EXCEPTIONS)
|
||||||
std::rethrow_exception(result_.get_error());
|
std::rethrow_exception(result_.get_exception());
|
||||||
#else // CONTINUABLE_WITH_EXCEPTIONS
|
#else // CONTINUABLE_WITH_EXCEPTIONS
|
||||||
// Returning error types in await isn't supported as of now
|
// Returning error types in await isn't supported as of now
|
||||||
util::trap();
|
util::trap();
|
||||||
@ -153,12 +157,12 @@ private:
|
|||||||
/// Resolve the continuation through the result
|
/// Resolve the continuation through the result
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void resolve(Args&&... args) {
|
void resolve(Args&&... args) {
|
||||||
// ...
|
result_.set_value(trait_t::wrap(std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve the continuation through an error
|
/// Resolve the continuation through an error
|
||||||
void resolve(types::dispatch_error_tag, types::error_type 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.
|
/// the C++ coroutine TS.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto create_awaiter(T&& continuable) {
|
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 awaiting
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
@ -240,11 +240,11 @@ public:
|
|||||||
assert(is_value());
|
assert(is_value());
|
||||||
return cast<T>();
|
return cast<T>();
|
||||||
}
|
}
|
||||||
T& get_exception() noexcept {
|
types::error_type& get_exception() noexcept {
|
||||||
assert(is_exception());
|
assert(is_exception());
|
||||||
return cast<types::error_type>();
|
return cast<types::error_type>();
|
||||||
}
|
}
|
||||||
T const& get_exception() const noexcept {
|
types::error_type const& get_exception() const noexcept {
|
||||||
assert(is_exception());
|
assert(is_exception());
|
||||||
return cast<types::error_type>();
|
return cast<types::error_type>();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,11 +51,6 @@ struct coroutine_traits<void, T...> {
|
|||||||
} // namespace experimental
|
} // namespace experimental
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
TYPED_TEST(single_dimension_tests, is_awaitable) {
|
|
||||||
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto mk() {
|
auto mk() {
|
||||||
return cti::make_continuable<void>([](auto&& promise) {
|
return cti::make_continuable<void>([](auto&& promise) {
|
||||||
// ...
|
// ...
|
||||||
@ -66,7 +61,15 @@ auto mk() {
|
|||||||
void teststhh() {
|
void teststhh() {
|
||||||
auto c = mk();
|
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
|
#endif // CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user