mirror of
https://github.com/Naios/continuable.git
synced 2025-12-07 01:06:44 +08:00
More work on the sequential compositioning
This commit is contained in:
parent
fd858a7ed7
commit
ba6c4cc905
@ -49,6 +49,7 @@ namespace detail {
|
|||||||
namespace composition {
|
namespace composition {
|
||||||
struct composition_strategy_all_tag {};
|
struct composition_strategy_all_tag {};
|
||||||
struct composition_strategy_any_tag {};
|
struct composition_strategy_any_tag {};
|
||||||
|
struct composition_strategy_any_fail_fast_tag {};
|
||||||
struct composition_strategy_seq_tag {};
|
struct composition_strategy_seq_tag {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -60,6 +61,12 @@ struct is_composition_strategy<composition_strategy_all_tag> // ...
|
|||||||
template <>
|
template <>
|
||||||
struct is_composition_strategy<composition_strategy_any_tag> // ...
|
struct is_composition_strategy<composition_strategy_any_tag> // ...
|
||||||
: std::true_type {};
|
: std::true_type {};
|
||||||
|
template <>
|
||||||
|
struct is_composition_strategy<composition_strategy_any_fail_fast_tag> // ...
|
||||||
|
: std::true_type {};
|
||||||
|
template <>
|
||||||
|
struct is_composition_strategy<composition_strategy_seq_tag> // ...
|
||||||
|
: std::true_type {};
|
||||||
|
|
||||||
/// Adds the given continuation tuple to the left composition
|
/// Adds the given continuation tuple to the left composition
|
||||||
template <typename... LeftArgs, typename... RightArgs>
|
template <typename... LeftArgs, typename... RightArgs>
|
||||||
@ -158,7 +165,7 @@ struct consume_ownership {
|
|||||||
template <typename Continuable,
|
template <typename Continuable,
|
||||||
std::enable_if_t<base::is_continuable<
|
std::enable_if_t<base::is_continuable<
|
||||||
std::decay_t<Continuable>>::value>* = nullptr>
|
std::decay_t<Continuable>>::value>* = nullptr>
|
||||||
void operator()(Continuable& continuable) noexcept {
|
void operator()(Continuable&& continuable) noexcept {
|
||||||
util::ownership other = base::attorney::ownership_of(continuable);
|
util::ownership other = base::attorney::ownership_of(continuable);
|
||||||
|
|
||||||
assert(other.is_acquired() && "Only valid continuables should be passed!");
|
assert(other.is_acquired() && "Only valid continuables should be passed!");
|
||||||
|
|||||||
@ -163,10 +163,61 @@ auto make_all_result_submitter(Callback&& callback,
|
|||||||
/// A callable object to merge multiple signature hints together
|
/// A callable object to merge multiple signature hints together
|
||||||
struct entry_merger {
|
struct entry_merger {
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
constexpr auto operator()(T&... entries) const noexcept {
|
constexpr auto operator()(T&&...) const noexcept {
|
||||||
return traits::merge(hints::hint_of(traits::identity_of(entries))...);
|
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 std::make_tuple(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>{}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Converts the given argument to a tuple if it isn't a tuple already
|
||||||
|
template <typename T>
|
||||||
|
constexpr auto tupelize(T&& arg) {
|
||||||
|
return std::make_tuple(std::forward<T>(arg));
|
||||||
|
}
|
||||||
|
/// Converts the given argument to a tuple if it isn't a tuple already
|
||||||
|
template <typename... T>
|
||||||
|
constexpr auto tupelize(std::tuple<T...> arg) {
|
||||||
|
return std::move(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Lift the first tuple hierarchy inside the given tuple
|
||||||
|
template <typename T>
|
||||||
|
constexpr auto flatten(T&& tuple) {
|
||||||
|
return traits::unpack(std::forward<T>(tuple), [](auto&&... args) {
|
||||||
|
return std::tuple_cat(tupelize(std::forward<decltype(args)>(args))...);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Composition>
|
||||||
|
constexpr auto deduce_hint(Composition&& composition) {
|
||||||
|
auto deduced = flatten(
|
||||||
|
map_pack(all_hint_deducer{}, std::forward<Composition>(composition)));
|
||||||
|
|
||||||
|
return traits::unpack(std::move(deduced), [](auto... args) {
|
||||||
|
return hints::signature_hint_tag<decltype(args)...>{};
|
||||||
|
});
|
||||||
|
}
|
||||||
} // namespace all
|
} // namespace all
|
||||||
|
|
||||||
/// Finalizes the all logic of a given composition
|
/// Finalizes the all logic of a given composition
|
||||||
@ -174,8 +225,7 @@ template <>
|
|||||||
struct composition_finalizer<composition_strategy_all_tag> {
|
struct composition_finalizer<composition_strategy_all_tag> {
|
||||||
template <typename Composition>
|
template <typename Composition>
|
||||||
static constexpr auto hint() {
|
static constexpr auto hint() {
|
||||||
return decltype(
|
return decltype(all::deduce_hint(std::declval<Composition>())){};
|
||||||
traits::unpack(std::declval<Composition>(), all::entry_merger{})){};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finalizes the all logic of a given composition
|
/// Finalizes the all logic of a given composition
|
||||||
|
|||||||
@ -179,6 +179,10 @@ struct composition_finalizer<composition_strategy_any_tag> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct composition_finalizer<composition_strategy_any_fail_fast_tag>
|
||||||
|
: composition_finalizer<composition_strategy_any_tag> {};
|
||||||
} // namespace composition
|
} // namespace composition
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace cti
|
} // namespace cti
|
||||||
|
|||||||
@ -79,7 +79,8 @@ struct result_extractor_mapper {
|
|||||||
}
|
}
|
||||||
/// Initialize a multiple values as tuple
|
/// Initialize a multiple values as tuple
|
||||||
template <typename First, typename Second, typename... Args>
|
template <typename First, typename Second, typename... Args>
|
||||||
static constexpr auto initialize(hints::signature_hint_tag<>) {
|
static constexpr auto
|
||||||
|
initialize(hints::signature_hint_tag<First, Second, Args...>) {
|
||||||
// TODO Fix non default constructible values
|
// TODO Fix non default constructible values
|
||||||
return std::make_tuple(First{}, Second{}, Args{}...);
|
return std::make_tuple(First{}, Second{}, Args{}...);
|
||||||
}
|
}
|
||||||
@ -116,7 +117,6 @@ struct result_relocator_mapper {
|
|||||||
void traverse(traversal::container_category_tag<false, false>, Index* index,
|
void traverse(traversal::container_category_tag<false, false>, Index* index,
|
||||||
Result* result) {
|
Result* result) {
|
||||||
|
|
||||||
evaluator(index, result);
|
|
||||||
traverse_one(traits::is_invocable<Evaluator, Index, Result>{}, index,
|
traverse_one(traits::is_invocable<Evaluator, Index, Result>{}, index,
|
||||||
result);
|
result);
|
||||||
}
|
}
|
||||||
@ -186,7 +186,6 @@ constexpr void relocate_index_pack(Relocator&& relocator, Index* index,
|
|||||||
|
|
||||||
mapper.traverse(tag, index, target);
|
mapper.traverse(tag, index, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace remapping
|
} // namespace remapping
|
||||||
} // namespace composition
|
} // namespace composition
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
@ -90,7 +90,8 @@ struct result_indexer_mapper {
|
|||||||
auto operator()(T& continuable) {
|
auto operator()(T& continuable) {
|
||||||
auto constexpr const hint = hints::hint_of(traits::identify<T>{});
|
auto constexpr const hint = hints::hint_of(traits::identify<T>{});
|
||||||
|
|
||||||
using target = decltype(result_extractor_mapper::initialize(hint));
|
using target =
|
||||||
|
decltype(remapping::detail::result_extractor_mapper::initialize(hint));
|
||||||
|
|
||||||
using type = indexed_continuable<std::decay_t<T>, target>;
|
using type = indexed_continuable<std::decay_t<T>, target>;
|
||||||
return type{std::move(continuable), nullptr};
|
return type{std::move(continuable), nullptr};
|
||||||
@ -138,7 +139,7 @@ struct sequential_dispatch_data {
|
|||||||
|
|
||||||
template <typename Data>
|
template <typename Data>
|
||||||
class sequential_dispatch_visitor
|
class sequential_dispatch_visitor
|
||||||
: std::enable_shared_from_this<sequential_dispatch_visitor<Data>> {
|
: public std::enable_shared_from_this<sequential_dispatch_visitor<Data>> {
|
||||||
|
|
||||||
Data data_;
|
Data data_;
|
||||||
|
|
||||||
@ -146,16 +147,19 @@ public:
|
|||||||
explicit sequential_dispatch_visitor(Data&& data) : data_(std::move(data)) {
|
explicit sequential_dispatch_visitor(Data&& data) : data_(std::move(data)) {
|
||||||
// Assign the address of each result target to the corresponding
|
// Assign the address of each result target to the corresponding
|
||||||
// indexed continuable.
|
// indexed continuable.
|
||||||
relocate_index_pack(index_relocator{}, &data.index, &data.result);
|
remapping::relocate_index_pack(index_relocator{}, &data.index,
|
||||||
|
&data.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~sequential_dispatch_visitor() = default;
|
||||||
|
|
||||||
/// Returns the pack that should be traversed
|
/// Returns the pack that should be traversed
|
||||||
auto& head() {
|
auto& head() {
|
||||||
return data_.index;
|
return data_.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Index,
|
template <typename Index, std::enable_if_t<is_indexed_continuable<
|
||||||
std::enable_if_t<is_indexed_continuable<Index>::value>* = nullptr>
|
std::decay_t<Index>>::value>* = nullptr>
|
||||||
bool operator()(async_traverse_visit_tag, Index&& /*index*/) {
|
bool operator()(async_traverse_visit_tag, Index&& /*index*/) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -165,7 +169,7 @@ public:
|
|||||||
|
|
||||||
std::move(index.continuable)
|
std::move(index.continuable)
|
||||||
.then([ target = index.target,
|
.then([ target = index.target,
|
||||||
next = std::forward<N>(next) ](auto&&... args) {
|
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 = wrap(std::forward<decltype(args)>(args)...);
|
||||||
@ -177,10 +181,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void operator()(async_traverse_complete_tag, T&& pack) {
|
void operator()(async_traverse_complete_tag, T&& /*pack*/) {
|
||||||
// Remove void result guard tags
|
// Remove void result guard tags
|
||||||
auto cleaned =
|
auto cleaned = all::flatten(
|
||||||
map_pack(remapping::clean_void_results{}, std::forward<T>(pack));
|
map_pack(remapping::clean_void_results{}, std::move(data_.result)));
|
||||||
|
|
||||||
// Call the final callback with the cleaned result
|
// Call the final callback with the cleaned result
|
||||||
traits::unpack(std::move(cleaned), std::move(data_.callback));
|
traits::unpack(std::move(cleaned), std::move(data_.callback));
|
||||||
@ -193,8 +197,7 @@ template <>
|
|||||||
struct composition_finalizer<composition_strategy_seq_tag> {
|
struct composition_finalizer<composition_strategy_seq_tag> {
|
||||||
template <typename Composition>
|
template <typename Composition>
|
||||||
static constexpr auto hint() {
|
static constexpr auto hint() {
|
||||||
return decltype(
|
return decltype(all::deduce_hint(std::declval<Composition>())){};
|
||||||
traits::unpack(std::declval<Composition>(), all::entry_merger{})){};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finalizes the all logic of a given composition
|
/// Finalizes the all logic of a given composition
|
||||||
|
|||||||
@ -68,7 +68,7 @@ struct my_callable {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int, char**) {
|
void old() {
|
||||||
http_request("github.com").next(my_callable{});
|
http_request("github.com").next(my_callable{});
|
||||||
|
|
||||||
http_request("github.com") | [](std::string) {
|
http_request("github.com") | [](std::string) {
|
||||||
@ -118,3 +118,13 @@ int main(int, char**) {
|
|||||||
// ...
|
// ...
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
using namespace cti::detail;
|
||||||
|
|
||||||
|
apply_composition(composition::composition_strategy_seq_tag{},
|
||||||
|
cti::make_ready_continuable(0, 1), 2)
|
||||||
|
.then([](int a0, int a1, int a2) {
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user