mirror of
https://github.com/Naios/continuable.git
synced 2025-12-07 01:06:44 +08:00
Start to work on rewriting the all composition
This commit is contained in:
parent
375e376db8
commit
1853ec8b42
@ -49,30 +49,55 @@ namespace cti {
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
namespace composition {
|
namespace composition {
|
||||||
namespace all {
|
namespace all {
|
||||||
template <std::size_t Pos, typename T>
|
struct all_hint_deducer {
|
||||||
constexpr void assign(traits::size_constant<Pos> /*pos*/, T& /*storage*/) {
|
static constexpr auto deduce(hints::signature_hint_tag<>) noexcept
|
||||||
// ...
|
-> decltype(spread_this());
|
||||||
}
|
|
||||||
template <std::size_t Pos, typename T, typename Current, typename... Args>
|
template <typename First>
|
||||||
void assign(traits::size_constant<Pos> pos, T& storage, Current&& current,
|
static constexpr auto deduce(hints::signature_hint_tag<First>) -> First;
|
||||||
Args&&... args) {
|
|
||||||
// TODO Improve this -> linear instantiation
|
template <typename First, typename Second, typename... Args>
|
||||||
std::get<Pos>(storage) = std::forward<Current>(current);
|
static constexpr auto
|
||||||
assign(pos + traits::size_constant_of<1>(), storage,
|
deduce(hints::signature_hint_tag<First, Second, Args...>)
|
||||||
std::forward<Args>(args)...);
|
-> decltype(spread_this(std::declval<First>(), std::declval<Second>(),
|
||||||
}
|
std::declval<Args>()...));
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename T,
|
||||||
|
std::enable_if_t<base::is_continuable<std::decay_t<T>>::value>* = nullptr>
|
||||||
|
auto operator()(T&& /*continuable*/) const
|
||||||
|
-> decltype(deduce(hints::hint_of(traits::identify<T>{})));
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr auto deduce_from_pack(traits::identity<void>)
|
||||||
|
-> hints::signature_hint_tag<>;
|
||||||
|
template <typename... T>
|
||||||
|
constexpr auto deduce_from_pack(traits::identity<std::tuple<T...>>)
|
||||||
|
-> hints::signature_hint_tag<T...>;
|
||||||
|
template <typename T>
|
||||||
|
constexpr auto deduce_from_pack(traits::identity<T>)
|
||||||
|
-> hints::signature_hint_tag<T>;
|
||||||
|
|
||||||
|
// We must guard the mapped type against to be void since this represents an
|
||||||
|
// empty signature hint.
|
||||||
|
template <typename Composition>
|
||||||
|
constexpr auto deduce_hint(Composition && /*composition*/)
|
||||||
|
-> decltype(deduce_from_pack(
|
||||||
|
traits::identity<decltype(map_pack(all_hint_deducer{},
|
||||||
|
std::declval<Composition>()))>{})){};
|
||||||
|
|
||||||
/// Caches the partial results and invokes the callback when all results
|
/// Caches the partial results and invokes the callback when all results
|
||||||
/// are arrived. This class is thread safe.
|
/// are arrived. This class is thread safe.
|
||||||
template <typename T, std::size_t Submissions, typename... Args>
|
template <typename Callback, typename Result>
|
||||||
class all_result_submitter : public std::enable_shared_from_this<
|
class all_result_submitter : public std::enable_shared_from_this<
|
||||||
all_result_submitter<T, Submissions, Args...>>,
|
all_result_submitter<Callback, Result>>,
|
||||||
public util::non_movable {
|
public util::non_movable {
|
||||||
|
|
||||||
T callback_;
|
Callback callback_;
|
||||||
|
Result result_;
|
||||||
|
|
||||||
std::atomic<std::size_t> left_;
|
std::atomic<std::size_t> left_;
|
||||||
std::once_flag flag_;
|
std::once_flag flag_;
|
||||||
std::tuple<Args...> result_;
|
|
||||||
|
|
||||||
template <std::size_t From, std::size_t To, typename... PartialArgs>
|
template <std::size_t From, std::size_t To, typename... PartialArgs>
|
||||||
void resolve(traits::size_constant<From> from, traits::size_constant<To>,
|
void resolve(traits::size_constant<From> from, traits::size_constant<To>,
|
||||||
@ -118,95 +143,47 @@ class all_result_submitter : public std::enable_shared_from_this<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t From, std::size_t To>
|
template <typename Target>
|
||||||
struct partial_all_callback {
|
struct partial_all_callback {
|
||||||
|
Target* target_;
|
||||||
std::shared_ptr<all_result_submitter> me_;
|
std::shared_ptr<all_result_submitter> me_;
|
||||||
|
|
||||||
template <typename... PartialArgs>
|
template <typename... PartialArgs>
|
||||||
void operator()(PartialArgs&&... args) && {
|
void operator()(PartialArgs&&... args) && {
|
||||||
me_->resolve(traits::size_constant<From>{}, traits::size_constant<To>{},
|
|
||||||
std::forward<PartialArgs>(args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... PartialArgs>
|
template <typename... PartialArgs>
|
||||||
void set_value(PartialArgs&&... args) {
|
void operator()(types::dispatch_error_tag, types::error_type) && {
|
||||||
std::move (*this)(std::forward<PartialArgs>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_exception(types::error_type error) {
|
|
||||||
std::move (*this)(types::dispatch_error_tag{}, std::move(error));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit all_result_submitter(T callback)
|
explicit all_result_submitter(Callback callback, Result&& result)
|
||||||
: callback_(std::move(callback)), left_(Submissions) {
|
: callback_(std::move(callback)), result_(std::move(result)), left_(1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a submitter which submits it's result into the tuple
|
/// Creates a submitter which submits it's result into the storage
|
||||||
template <std::size_t From, std::size_t To>
|
template <typename Target>
|
||||||
auto create_callback(traits::size_constant<From> /*from*/,
|
auto create_callback(Target* target) {
|
||||||
traits::size_constant<To> /*to*/) {
|
left_.fetch_add(1, std::memory_order_seq_cst);
|
||||||
return partial_all_callback<From, To>{this->shared_from_this()};
|
return partial_all_callback<std::decay_t<Target>>{target,
|
||||||
|
this->shared_from_this()};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initially the counter is created with an initial count of 1 in order
|
||||||
|
/// to prevent that the composition is finished before all callbacks
|
||||||
|
/// were registered.
|
||||||
|
void start_accept() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Creates a submitter which caches the intermediate results of `all` chains
|
struct continuable_dispatcher {
|
||||||
template <typename Callback, std::size_t Submissions, typename... Args>
|
template <typename Index, typename Target,
|
||||||
auto make_all_result_submitter(Callback&& callback,
|
std::enable_if_t<
|
||||||
traits::size_constant<Submissions>,
|
base::is_continuable<std::decay_t<Index>>::value>* = nullptr>
|
||||||
traits::identity<Args...>) {
|
auto operator()(Index* index, Target* target) const noexcept {
|
||||||
return std::make_shared<all_result_submitter<std::decay_t<decltype(callback)>,
|
|
||||||
Submissions, Args...>>(
|
|
||||||
std::forward<decltype(callback)>(callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A callable object to merge multiple signature hints together
|
|
||||||
struct entry_merger {
|
|
||||||
template <typename... T>
|
|
||||||
constexpr auto operator()(T&&...) const noexcept {
|
|
||||||
return traits::merge(hints::hint_of(traits::identify<T>())...);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct all_hint_deducer {
|
|
||||||
static constexpr auto deduce(hints::signature_hint_tag<>) noexcept {
|
|
||||||
return spread_this();
|
|
||||||
}
|
|
||||||
template <typename First>
|
|
||||||
static constexpr auto deduce(hints::signature_hint_tag<First>) {
|
|
||||||
return First{};
|
|
||||||
}
|
|
||||||
template <typename First, typename Second, typename... Args>
|
|
||||||
static constexpr auto
|
|
||||||
deduce(hints::signature_hint_tag<First, Second, Args...>) {
|
|
||||||
return spread_this(First{}, Second{}, Args{}...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <
|
|
||||||
typename T,
|
|
||||||
std::enable_if_t<base::is_continuable<std::decay_t<T>>::value>* = nullptr>
|
|
||||||
auto operator()(T&& /*continuable*/) const {
|
|
||||||
return deduce(hints::hint_of(traits::identify<T>{}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr auto deduce_from_pack(traits::identity<void>)
|
|
||||||
-> hints::signature_hint_tag<>;
|
|
||||||
template <typename... T>
|
|
||||||
constexpr auto deduce_from_pack(traits::identity<std::tuple<T...>>)
|
|
||||||
-> hints::signature_hint_tag<T...>;
|
|
||||||
template <typename T>
|
|
||||||
constexpr auto deduce_from_pack(traits::identity<T>)
|
|
||||||
-> hints::signature_hint_tag<T>;
|
|
||||||
|
|
||||||
// We must guard the mapped type against to be void since this represents an
|
|
||||||
// empty signature hint.
|
|
||||||
template <typename Composition>
|
|
||||||
constexpr auto deduce_hint(Composition && /*composition*/)
|
|
||||||
-> decltype(deduce_from_pack(
|
|
||||||
traits::identity<decltype(map_pack(all_hint_deducer{},
|
|
||||||
std::declval<Composition>()))>{})){};
|
|
||||||
} // namespace all
|
} // namespace all
|
||||||
|
|
||||||
/// Finalizes the all logic of a given composition
|
/// Finalizes the all logic of a given composition
|
||||||
@ -223,52 +200,10 @@ struct composition_finalizer<composition_strategy_all_tag> {
|
|||||||
return [composition = std::forward<Composition>(composition)](
|
return [composition = std::forward<Composition>(composition)](
|
||||||
auto&& callback) mutable {
|
auto&& callback) mutable {
|
||||||
|
|
||||||
// We mark the current 2-dimensional position through a pair:
|
auto result =
|
||||||
// std::pair<size_constant<?>, size_constant<?>>
|
remapping::create_result_pack(std::forward<Composition>(composition));
|
||||||
// ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
|
|
||||||
// Continuation pos Result pos
|
|
||||||
constexpr auto const begin = std::make_pair(
|
|
||||||
traits::size_constant_of<0>(), traits::size_constant_of<0>());
|
|
||||||
constexpr auto const pack = traits::identify<decltype(composition)>{};
|
|
||||||
constexpr auto const end = traits::pack_size_of(pack);
|
|
||||||
auto const condition = [=](auto pos) { return pos.first < end; };
|
|
||||||
|
|
||||||
constexpr auto const signature = hint<Composition>();
|
|
||||||
|
|
||||||
// Create the result submitter which caches all results and invokes
|
|
||||||
// the final callback upon completion.
|
|
||||||
auto submitter = all::make_all_result_submitter(
|
|
||||||
std::forward<decltype(callback)>(callback), end, signature);
|
|
||||||
|
|
||||||
// Invoke every continuation with it's callback of the submitter
|
|
||||||
traits::static_while(begin, condition, [&](auto current) mutable {
|
|
||||||
auto entry =
|
|
||||||
std::move(std::get<decltype(current.first)::value>(composition));
|
|
||||||
|
|
||||||
// This is the length of the arguments of the current continuable
|
|
||||||
constexpr auto const arg_size =
|
|
||||||
traits::pack_size_of(hints::hint_of(traits::identity_of(entry)));
|
|
||||||
|
|
||||||
// The next position in the result tuple
|
|
||||||
constexpr auto const next = current.second + arg_size;
|
|
||||||
|
|
||||||
// Invoke the continuation with the associated submission callback
|
|
||||||
base::attorney::invoke_continuation(
|
|
||||||
std::move(entry), submitter->create_callback(current.second, next));
|
|
||||||
|
|
||||||
return std::make_pair(current.first + traits::size_constant_of<1>(),
|
|
||||||
next);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*template <typename Composition>
|
|
||||||
static auto finalize_new(Composition&& composition) {
|
|
||||||
return [composition = std::forward<Composition>(composition)](
|
|
||||||
auto&& callback) mutable {
|
|
||||||
// TODO
|
|
||||||
};
|
|
||||||
}*/
|
|
||||||
};
|
};
|
||||||
} // namespace composition
|
} // namespace composition
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
@ -81,6 +81,20 @@ struct unpack_result_guards {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr void_result_guard wrap() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
template <typename First>
|
||||||
|
constexpr decltype(auto) wrap(First&& first) {
|
||||||
|
return std::forward<First>(first);
|
||||||
|
}
|
||||||
|
template <typename First, typename Second, typename... Rest>
|
||||||
|
constexpr decltype(auto) wrap(First&& first, Second&& second, Rest&&... rest) {
|
||||||
|
return std::make_tuple(std::forward<First>(first),
|
||||||
|
std::forward<Second>(second),
|
||||||
|
std::forward<Rest>(rest)...);
|
||||||
|
}
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
struct result_extractor_mapper {
|
struct result_extractor_mapper {
|
||||||
/// Create slots for a void result which is removed later.
|
/// Create slots for a void result which is removed later.
|
||||||
|
|||||||
@ -42,6 +42,7 @@
|
|||||||
#include <continuable/detail/composition-all.hpp>
|
#include <continuable/detail/composition-all.hpp>
|
||||||
#include <continuable/detail/composition-remapping.hpp>
|
#include <continuable/detail/composition-remapping.hpp>
|
||||||
#include <continuable/detail/traits.hpp>
|
#include <continuable/detail/traits.hpp>
|
||||||
|
#include <continuable/detail/util.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -122,20 +123,6 @@ struct index_relocator {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr remapping::void_result_guard wrap() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
template <typename First>
|
|
||||||
constexpr decltype(auto) wrap(First&& first) {
|
|
||||||
return std::forward<First>(first);
|
|
||||||
}
|
|
||||||
template <typename First, typename Second, typename... Rest>
|
|
||||||
constexpr decltype(auto) wrap(First&& first, Second&& second, Rest&&... rest) {
|
|
||||||
return std::make_tuple(std::forward<First>(first),
|
|
||||||
std::forward<Second>(second),
|
|
||||||
std::forward<Rest>(rest)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Callback, typename Index, typename Result>
|
template <typename Callback, typename Index, typename Result>
|
||||||
struct sequential_dispatch_data {
|
struct sequential_dispatch_data {
|
||||||
Callback callback;
|
Callback callback;
|
||||||
@ -145,7 +132,8 @@ struct sequential_dispatch_data {
|
|||||||
|
|
||||||
template <typename Data>
|
template <typename Data>
|
||||||
class sequential_dispatch_visitor
|
class sequential_dispatch_visitor
|
||||||
: public std::enable_shared_from_this<sequential_dispatch_visitor<Data>> {
|
: public std::enable_shared_from_this<sequential_dispatch_visitor<Data>>,
|
||||||
|
public util::non_movable {
|
||||||
|
|
||||||
Data data_;
|
Data data_;
|
||||||
|
|
||||||
@ -181,7 +169,7 @@ public:
|
|||||||
next = std::forward<N>(next) ](auto&&... args) mutable {
|
next = std::forward<N>(next) ](auto&&... args) mutable {
|
||||||
|
|
||||||
// Assign the result to the target
|
// Assign the result to the target
|
||||||
*target = wrap(std::forward<decltype(args)>(args)...);
|
*target = remapping::wrap(std::forward<decltype(args)>(args)...);
|
||||||
|
|
||||||
// Continue the asynchronous sequential traversal
|
// Continue the asynchronous sequential traversal
|
||||||
next();
|
next();
|
||||||
|
|||||||
@ -142,7 +142,7 @@ auto connect(Strategy strategy, continuable_base<LData, LAnnotation>&& left,
|
|||||||
template <typename Strategy>
|
template <typename Strategy>
|
||||||
struct composition_finalizer;
|
struct composition_finalizer;
|
||||||
|
|
||||||
/// Finalizes the any logic of a given composition
|
/// Finalizes the connection logic of a given composition
|
||||||
template <typename Data, typename Strategy>
|
template <typename Data, typename Strategy>
|
||||||
auto finalize_composition(continuable_base<Data, Strategy>&& continuation) {
|
auto finalize_composition(continuable_base<Data, Strategy>&& continuation) {
|
||||||
using finalizer = composition_finalizer<Strategy>;
|
using finalizer = composition_finalizer<Strategy>;
|
||||||
@ -197,6 +197,7 @@ struct prepare_continuables {
|
|||||||
continuable.freeze();
|
continuable.freeze();
|
||||||
|
|
||||||
// Materialize every continuable
|
// Materialize every continuable
|
||||||
|
// TODO Actually we would just need to consume the data here
|
||||||
return base::attorney::materialize(std::forward<Continuable>(continuable));
|
return base::attorney::materialize(std::forward<Continuable>(continuable));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user