mirror of
https://github.com/Naios/continuable.git
synced 2026-01-01 03:12:12 +08:00
Specialize the continuation chainer in case ready continuables are chained
This commit is contained in:
parent
9ceee76647
commit
7273891a4c
@ -90,13 +90,13 @@ using is_continuable = detail::base::is_continuable<T>;
|
||||
///
|
||||
/// \since 1.0.0
|
||||
template <typename Data, typename Annotation>
|
||||
class continuable_base
|
||||
: public detail::annotation_trait<Annotation>::template //
|
||||
annotation_base<continuable_base<Data, Annotation>> {
|
||||
class continuable_base {
|
||||
|
||||
/// \cond false
|
||||
using ownership = detail::util::ownership;
|
||||
|
||||
using annotation_trait = detail::annotation_trait<Annotation>;
|
||||
|
||||
template <typename, typename>
|
||||
friend class continuable_base;
|
||||
friend struct detail::base::attorney;
|
||||
@ -562,7 +562,6 @@ public:
|
||||
detail::base::finalize_continuation(std::move(*this));
|
||||
}
|
||||
|
||||
#ifdef CONTINUABLE_HAS_DOXYGEN
|
||||
/// Materializes the continuation expression template and finishes
|
||||
/// the current applied strategy such that the resulting continuable
|
||||
/// will always be a concrete type and Continuable::is_concrete holds.
|
||||
@ -587,8 +586,9 @@ public:
|
||||
/// on conversion.
|
||||
///
|
||||
/// \since 4.0.0
|
||||
unspecified finish() &&;
|
||||
#endif // CONTINUABLE_HAS_DOXYGEN
|
||||
auto finish() && {
|
||||
return annotation_trait::finish(std::move(*this));
|
||||
}
|
||||
|
||||
/// Predicate to check whether the cti::continuable_base is frozen or not.
|
||||
///
|
||||
|
||||
@ -189,7 +189,8 @@ struct connection_finalizer<connection_strategy_all_tag> {
|
||||
/// Specialization for a connection annotation
|
||||
template <>
|
||||
struct annotation_trait<connection::connection_strategy_all_tag>
|
||||
: connection::connection_annotation_trait {};
|
||||
: connection::connection_annotation_trait<
|
||||
connection::connection_strategy_all_tag> {};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace cti
|
||||
|
||||
@ -193,10 +193,11 @@ struct connection_finalizer<connection_strategy_any_tag> {
|
||||
};
|
||||
} // namespace connection
|
||||
|
||||
/// Specialization for a connection annotation
|
||||
/// Specialization for a connection annotation
|
||||
template <>
|
||||
struct annotation_trait<connection::connection_strategy_any_tag>
|
||||
: connection::connection_annotation_trait {};
|
||||
: connection::connection_annotation_trait<
|
||||
connection::connection_strategy_any_tag> {};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace cti
|
||||
|
||||
@ -164,7 +164,8 @@ struct connection_finalizer<connection_strategy_seq_tag> {
|
||||
/// Specialization for a connection annotation
|
||||
template <>
|
||||
struct annotation_trait<connection::connection_strategy_seq_tag>
|
||||
: connection::connection_annotation_trait {};
|
||||
: connection::connection_annotation_trait<
|
||||
connection::connection_strategy_seq_tag> {};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace cti
|
||||
|
||||
@ -124,25 +124,22 @@ auto connect(Strategy strategy, continuable_base<LData, LAnnotation>&& left,
|
||||
template <typename Strategy>
|
||||
struct connection_finalizer;
|
||||
|
||||
template <typename Strategy>
|
||||
struct connection_annotation_trait {
|
||||
/// Finalizes the connection logic of a given connection
|
||||
template <typename Continuable>
|
||||
struct annotation_base;
|
||||
template <typename Data, typename Strategy>
|
||||
struct annotation_base<continuable_base<Data, Strategy>> {
|
||||
/// Finalizes the connection logic of a given connection
|
||||
auto finish() && {
|
||||
using continuable_t = continuable_base<Data, Strategy>;
|
||||
auto&& continuation = std::move(*static_cast<continuable_t*>(this));
|
||||
static auto finish(Continuable&& continuable) {
|
||||
using continuable_t = traits::unrefcv_t<Continuable>;
|
||||
|
||||
using finalizer = connection_finalizer<Strategy>;
|
||||
using finalizer = connection_finalizer<Strategy>;
|
||||
|
||||
util::ownership ownership = base::attorney::ownership_of(continuation);
|
||||
auto connection = base::attorney::consume(std::move(continuation));
|
||||
util::ownership ownership = base::attorney::ownership_of(continuable);
|
||||
auto connection =
|
||||
base::attorney::consume(std::forward<Continuable>(continuable));
|
||||
|
||||
// Return a new continuable which
|
||||
return finalizer::finalize(std::move(connection), std::move(ownership));
|
||||
}
|
||||
};
|
||||
// Return a new continuable which
|
||||
return finalizer::finalize(std::move(connection), std::move(ownership));
|
||||
}
|
||||
};
|
||||
|
||||
class prepare_continuables {
|
||||
|
||||
@ -44,11 +44,9 @@ struct annotation_trait;
|
||||
template <typename... Args>
|
||||
struct annotation_trait<traits::identity<Args...>> {
|
||||
template <typename Continuable>
|
||||
struct annotation_base {
|
||||
Continuable&& finish() {
|
||||
return std::move(*static_cast<Continuable*>(this));
|
||||
}
|
||||
};
|
||||
static Continuable&& finish(Continuable&& continuable) {
|
||||
return std::forward<Continuable>(continuable);
|
||||
}
|
||||
};
|
||||
|
||||
namespace hints {
|
||||
@ -57,11 +55,9 @@ namespace hints {
|
||||
///
|
||||
/// This is the overload taking an arbitrary amount of args
|
||||
template <typename... HintArgs>
|
||||
struct from_args
|
||||
: std::common_type<traits::identity<HintArgs...>> {};
|
||||
struct from_args : std::common_type<traits::identity<HintArgs...>> {};
|
||||
template <>
|
||||
struct from_args<void>
|
||||
: std::common_type<traits::identity<>> {};
|
||||
struct from_args<void> : std::common_type<traits::identity<>> {};
|
||||
} // namespace hints
|
||||
} // namespace detail
|
||||
} // namespace cti
|
||||
|
||||
@ -761,8 +761,7 @@ struct chained_continuation<traits::identity<Args...>, HandleResults,
|
||||
if (is_ready) {
|
||||
// Invoke the proxy callback directly with the result to
|
||||
// avoid a potential type erasure.
|
||||
// traits::unpack(std::move(proxy),
|
||||
std::move(continuation_)(query_arg_t{});
|
||||
traits::unpack(std::move(proxy), std::move(continuation_)(query_arg_t{}));
|
||||
} else {
|
||||
// Invoke the continuation with a proxy callback.
|
||||
// The proxy callback is responsible for passing
|
||||
@ -779,6 +778,48 @@ struct chained_continuation<traits::identity<Args...>, HandleResults,
|
||||
util::unreachable();
|
||||
}
|
||||
};
|
||||
// Specialization to unpack ready continuables directly
|
||||
template <typename... Args, handle_results HandleResults,
|
||||
handle_errors HandleErrors, typename Callback, typename Executor>
|
||||
struct chained_continuation<traits::identity<Args...>, HandleResults,
|
||||
HandleErrors, ready_continuation<Args...>, Callback,
|
||||
Executor> {
|
||||
ready_continuation<Args...> continuation_;
|
||||
Callback callback_;
|
||||
Executor executor_;
|
||||
|
||||
explicit chained_continuation(ready_continuation<Args...> continuation,
|
||||
Callback callback, Executor executor)
|
||||
: continuation_(std::move(continuation)), callback_(std::move(callback)),
|
||||
executor_(std::move(executor)) {
|
||||
}
|
||||
|
||||
chained_continuation() = delete;
|
||||
~chained_continuation() = default;
|
||||
chained_continuation(chained_continuation const&) = delete;
|
||||
chained_continuation(chained_continuation&&) = default;
|
||||
chained_continuation& operator=(chained_continuation const&) = delete;
|
||||
chained_continuation& operator=(chained_continuation&&) = default;
|
||||
|
||||
template <typename NextCallback>
|
||||
void operator()(NextCallback&& next_callback) {
|
||||
auto proxy = callbacks::make_callback<traits::identity<Args...>,
|
||||
HandleResults, HandleErrors>(
|
||||
std::move(callback_), std::move(executor_),
|
||||
std::forward<decltype(next_callback)>(next_callback));
|
||||
|
||||
// Extract the result out of the ready continuable
|
||||
traits::unpack(std::move(proxy), std::move(continuation_)(query_arg_t{}));
|
||||
}
|
||||
|
||||
bool operator()(is_ready_arg_t) const noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::tuple<Args...> operator()(query_arg_t) {
|
||||
util::unreachable();
|
||||
}
|
||||
};
|
||||
|
||||
/// Chains a callback together with a continuation and returns a
|
||||
/// continuation:
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#define CONTINUABLE_DETAIL_UTIL_HPP_INCLUDED
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
@ -258,11 +259,12 @@ private:
|
||||
__builtin_unreachable();
|
||||
#elif defined(__has_builtin) && __has_builtin(__builtin_unreachable)
|
||||
__builtin_unreachable();
|
||||
#else
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Causes the application to exit abnormally because we are
|
||||
/// in an invalid state.
|
||||
/// Causes the application to exit abnormally.
|
||||
[[noreturn]] inline void trap() {
|
||||
#if defined(_MSC_VER)
|
||||
__debugbreak();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user