mirror of
https://github.com/Naios/continuable.git
synced 2025-12-06 16:56:44 +08:00
Expose finish() method in continuable_base which makes it possible
to materialize the continuable_base when using it as an expression template.
This commit is contained in:
parent
0657445466
commit
6969a9e392
@ -96,6 +96,11 @@ class continuable_base {
|
||||
friend class continuable_base;
|
||||
friend struct detail::base::attorney;
|
||||
|
||||
// The materializer which is used when this continuable_base is an
|
||||
// expression template such that is_connection_strategy<Annotation>::value
|
||||
// holds for the Annotation.
|
||||
using materializer = detail::connection::materializer<continuable_base>;
|
||||
|
||||
// The continuation type or intermediate result
|
||||
Data data_;
|
||||
// The transferable state which represents the validity of the object
|
||||
@ -126,7 +131,7 @@ public:
|
||||
/// the continuable by any object which is useful for type-erasure.
|
||||
template <typename OData, typename OAnnotation>
|
||||
continuable_base(continuable_base<OData, OAnnotation>&& other)
|
||||
: continuable_base(std::move(other).materialize().consume_data()) {
|
||||
: continuable_base(std::move(other).finish().consume_data()) {
|
||||
}
|
||||
|
||||
/// \cond false
|
||||
@ -241,7 +246,7 @@ public:
|
||||
E&& executor = detail::types::this_thread_executor_tag{}) && {
|
||||
return detail::base::chain_continuation<detail::base::handle_results::yes,
|
||||
detail::base::handle_errors::no>(
|
||||
std::move(*this).materialize(), std::forward<T>(callback),
|
||||
std::move(*this).finish(), std::forward<T>(callback),
|
||||
std::forward<E>(executor));
|
||||
}
|
||||
|
||||
@ -267,7 +272,7 @@ public:
|
||||
template <typename OData, typename OAnnotation>
|
||||
auto then(continuable_base<OData, OAnnotation>&& continuation) && {
|
||||
return std::move(*this).then(
|
||||
detail::base::wrap_continuation(std::move(continuation).materialize()));
|
||||
detail::base::wrap_continuation(std::move(continuation).finish()));
|
||||
}
|
||||
|
||||
/// Main method of the continuable_base to catch exceptions and error codes
|
||||
@ -314,7 +319,7 @@ public:
|
||||
E&& executor = detail::types::this_thread_executor_tag{}) && {
|
||||
return detail::base::chain_continuation<detail::base::handle_results::no,
|
||||
detail::base::handle_errors::plain>(
|
||||
std::move(*this).materialize(), std::forward<T>(callback),
|
||||
std::move(*this).finish(), std::forward<T>(callback),
|
||||
std::forward<E>(executor));
|
||||
}
|
||||
|
||||
@ -375,7 +380,7 @@ public:
|
||||
E&& executor = detail::types::this_thread_executor_tag{}) && {
|
||||
return detail::base::chain_continuation<
|
||||
detail::base::handle_results::yes,
|
||||
detail::base::handle_errors::forward>(std::move(*this).materialize(),
|
||||
detail::base::handle_errors::forward>(std::move(*this).finish(),
|
||||
std::forward<T>(callback),
|
||||
std::forward<E>(executor));
|
||||
}
|
||||
@ -390,7 +395,7 @@ public:
|
||||
/// \since 2.0.0
|
||||
template <typename T>
|
||||
auto apply(T&& transform) && {
|
||||
return std::forward<T>(transform)(std::move(*this).materialize());
|
||||
return std::forward<T>(transform)(std::move(*this).finish());
|
||||
}
|
||||
|
||||
/// The pipe operator | is an alias for the continuable::then method.
|
||||
@ -585,6 +590,33 @@ public:
|
||||
return std::move(*this);
|
||||
}
|
||||
|
||||
/// Materializes the continuation expression template and finishes
|
||||
/// the current applied strategy.
|
||||
///
|
||||
/// This can be used in the case where we are chaining continuations lazily
|
||||
/// through a strategy, for instance when applying operators for
|
||||
/// expressing connections and then want to return a materialized
|
||||
/// continuable_base which uses the strategy respectively.
|
||||
/// ```cpp
|
||||
/// auto do_both() {
|
||||
/// return (wait(10s) || wait_key_pressed(KEY_SPACE)).finish();
|
||||
/// }
|
||||
///
|
||||
/// // Without a call to finish() this would lead to
|
||||
/// // an unintended evaluation strategy:
|
||||
/// do_both() || wait(5s);
|
||||
/// ```
|
||||
///
|
||||
/// \note When using a type erased continuable_base such as
|
||||
/// `continuable<...>` this method doesn't need to be called
|
||||
/// since the continuable_base is materialized automatically
|
||||
/// on conversion.
|
||||
///
|
||||
/// \since 4.0.0
|
||||
auto finish() && {
|
||||
return materializer::apply(std::move(*this));
|
||||
}
|
||||
|
||||
/// \cond false
|
||||
#ifdef CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE
|
||||
/// \endcond
|
||||
@ -667,7 +699,7 @@ public:
|
||||
///
|
||||
/// \since 2.0.0
|
||||
auto operator co_await() && {
|
||||
return detail::awaiting::create_awaiter(std::move(*this).materialize());
|
||||
return detail::awaiting::create_awaiter(std::move(*this).finish());
|
||||
}
|
||||
/// \cond false
|
||||
#endif // CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE
|
||||
@ -678,11 +710,6 @@ private:
|
||||
ownership_.release();
|
||||
}
|
||||
|
||||
auto materialize() && {
|
||||
return detail::connection::materializer<continuable_base>::apply(
|
||||
std::move(*this));
|
||||
}
|
||||
|
||||
Data&& consume_data() && {
|
||||
assert_acquired();
|
||||
release();
|
||||
|
||||
@ -83,7 +83,7 @@ auto normalize(Strategy /*strategy*/,
|
||||
|
||||
// If the right continuation is a different strategy materialize it
|
||||
// in order to keep the precedence in cases where: `c1 && (c2 || c3)`.
|
||||
return std::make_tuple(base::attorney::materialize(std::move(continuation)));
|
||||
return std::make_tuple(std::move(continuation).finish());
|
||||
}
|
||||
/// - The continuable is inside the current strategy state:
|
||||
/// -> return the data of the tuple
|
||||
@ -179,7 +179,7 @@ public:
|
||||
|
||||
// Materialize every continuable
|
||||
// TODO Actually we would just need to consume the data here
|
||||
return base::attorney::materialize(std::forward<Continuable>(continuable));
|
||||
return std::forward<Continuable>(continuable).finish();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -82,16 +82,11 @@ struct attorney {
|
||||
static auto
|
||||
invoke_continuation(continuable_base<Data, Annotation>&& continuation,
|
||||
Callback&& callback) noexcept {
|
||||
auto materialized = std::move(continuation).materialize();
|
||||
auto materialized = std::move(continuation).finish();
|
||||
materialized.release();
|
||||
return materialized.data_(std::forward<Callback>(callback));
|
||||
}
|
||||
|
||||
template <typename Data, typename Annotation>
|
||||
static auto materialize(continuable_base<Data, Annotation>&& continuation) {
|
||||
return std::move(continuation).materialize();
|
||||
}
|
||||
|
||||
template <typename Data, typename Annotation>
|
||||
static Data&&
|
||||
consume_data(continuable_base<Data, Annotation>&& continuation) {
|
||||
@ -167,8 +162,8 @@ template <typename Data, typename Annotation>
|
||||
constexpr auto
|
||||
invoker_of(traits::identity<continuable_base<Data, Annotation>>) {
|
||||
/// Get the hint of the unwrapped returned continuable
|
||||
using Type = decltype(attorney::materialize(
|
||||
std::declval<continuable_base<Data, Annotation>>()));
|
||||
using Type =
|
||||
decltype(std::declval<continuable_base<Data, Annotation>>().finish());
|
||||
|
||||
auto constexpr const hint = hints::hint_of(traits::identify<Type>{});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user