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