mirror of
https://github.com/Naios/continuable.git
synced 2025-12-06 16:56:44 +08:00
Calculate the connection hint directly from the intermediate result
This commit is contained in:
parent
49a097660b
commit
cd6f7445f0
@ -200,20 +200,28 @@ constexpr auto unbox_continuables(Args&&... args) {
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template <typename Callback, typename Data>
|
template <typename Callback, typename Data>
|
||||||
void finalize_impl(traits::identity<void>, Callback&& callback, Data&&) {
|
constexpr auto finalize_impl(traits::identity<void>, Callback&& callback,
|
||||||
std::forward<Callback>(callback)();
|
Data&&) {
|
||||||
|
return std::forward<Callback>(callback)();
|
||||||
}
|
}
|
||||||
template <typename... Args, typename Callback, typename Data>
|
template <typename... Args, typename Callback, typename Data>
|
||||||
void finalize_impl(traits::identity<std::tuple<Args...>>, Callback&& callback,
|
constexpr auto finalize_impl(traits::identity<std::tuple<Args...>>,
|
||||||
Data&& data) {
|
Callback&& callback, Data&& data) {
|
||||||
// Call the final callback with the cleaned result
|
// Call the final callback with the cleaned result
|
||||||
traits::unpack(unbox_continuables(std::forward<Data>(data)),
|
return traits::unpack(unbox_continuables(std::forward<Data>(data)),
|
||||||
std::forward<Callback>(callback));
|
std::forward<Callback>(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct hint_mapper {
|
||||||
|
template <typename... T>
|
||||||
|
constexpr auto operator()(T...) -> hints::signature_hint_tag<T...> {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename Callback, typename Data>
|
template <typename Callback, typename Data>
|
||||||
void finalize_data(Callback&& callback, Data&& data) {
|
constexpr auto finalize_data(Callback&& callback, Data&& data) {
|
||||||
using result_t = decltype(unbox_continuables(std::forward<Data>(data)));
|
using result_t = decltype(unbox_continuables(std::forward<Data>(data)));
|
||||||
// Guard the final result against void
|
// Guard the final result against void
|
||||||
return detail::finalize_impl(traits::identity<std::decay_t<result_t>>{},
|
return detail::finalize_impl(traits::identity<std::decay_t<result_t>>{},
|
||||||
@ -221,54 +229,10 @@ void finalize_data(Callback&& callback, Data&& data) {
|
|||||||
std::forward<Data>(data));
|
std::forward<Data>(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct all_hint_deducer {
|
template <typename Data>
|
||||||
static constexpr auto deduce(hints::signature_hint_tag<>) noexcept {
|
constexpr auto hint_of_data() {
|
||||||
return spread_this();
|
return decltype(finalize_data(detail::hint_mapper{}, std::declval<Data>())){};
|
||||||
}
|
|
||||||
|
|
||||||
template <typename First>
|
|
||||||
static constexpr auto deduce(hints::signature_hint_tag<First>) {
|
|
||||||
return unpack_lazy(lazy_value_t<First>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename First, typename Second, typename... Args>
|
|
||||||
static constexpr auto
|
|
||||||
deduce(hints::signature_hint_tag<First, Second, Args...>) {
|
|
||||||
return spread_this(unpack_lazy(lazy_value_t<First>{}),
|
|
||||||
unpack_lazy(lazy_value_t<Second>{}),
|
|
||||||
unpack_lazy(lazy_value_t<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*/) {
|
|
||||||
// Don't change this way since it addresses a GCC compiler bug:
|
|
||||||
// error: extra ';' [-Werror=pedantic]
|
|
||||||
// std::declval<Composition>()))>{})){};
|
|
||||||
using mapped_t =
|
|
||||||
decltype(map_pack(all_hint_deducer{}, std::declval<Composition>()));
|
|
||||||
using deduced_t = decltype(deduce_from_pack(traits::identity<mapped_t>{}));
|
|
||||||
return deduced_t{};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aggregated
|
} // namespace aggregated
|
||||||
} // namespace composition
|
} // namespace composition
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
@ -153,36 +153,36 @@ struct is_composition_strategy<composition_strategy_all_tag> // ...
|
|||||||
/// Finalizes the all logic of a given composition
|
/// Finalizes the all logic of a given composition
|
||||||
template <>
|
template <>
|
||||||
struct composition_finalizer<composition_strategy_all_tag> {
|
struct composition_finalizer<composition_strategy_all_tag> {
|
||||||
template <typename Composition>
|
|
||||||
static constexpr auto hint() {
|
|
||||||
return decltype(aggregated::deduce_hint(std::declval<Composition>())){};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Finalizes the all logic of a given composition
|
/// Finalizes the all logic of a given composition
|
||||||
template <typename Composition>
|
template <typename Composition>
|
||||||
static auto finalize(Composition&& composition) {
|
static auto finalize(Composition&& composition, util::ownership ownership) {
|
||||||
return [composition = std::forward<Composition>(composition)] // ...
|
// Create the target result from the composition
|
||||||
(auto&& callback) mutable {
|
auto result =
|
||||||
|
aggregated::box_continuables(std::forward<Composition>(composition));
|
||||||
|
|
||||||
// Create the target result from the composition
|
auto signature = aggregated::hint_of_data<decltype(result)>();
|
||||||
auto result = aggregated::box_continuables(std::move(composition));
|
|
||||||
|
|
||||||
using submitter_t =
|
return base::attorney::create(
|
||||||
all::result_submitter<std::decay_t<decltype(callback)>,
|
[result = std::move(result)](auto&& callback) mutable {
|
||||||
std::decay_t<decltype(result)>>;
|
|
||||||
|
|
||||||
// Create the shared state which holds the result and the final callback
|
using submitter_t =
|
||||||
auto state = std::make_shared<submitter_t>(
|
all::result_submitter<std::decay_t<decltype(callback)>,
|
||||||
std::forward<decltype(callback)>(callback), std::move(result));
|
std::decay_t<decltype(result)>>;
|
||||||
|
|
||||||
// Dispatch the continuables and store its partial result
|
// Create the shared state which holds the result and the final
|
||||||
// in the whole result
|
// callback
|
||||||
traverse_pack(all::continuable_dispatcher<submitter_t>{state},
|
auto state = std::make_shared<submitter_t>(
|
||||||
state->head());
|
std::forward<decltype(callback)>(callback), std::move(result));
|
||||||
|
|
||||||
// Finalize the composition if all results arrived in-place
|
// Dispatch the continuables and store its partial result
|
||||||
state->accept();
|
// in the whole result
|
||||||
};
|
traverse_pack(all::continuable_dispatcher<submitter_t>{state},
|
||||||
|
state->head());
|
||||||
|
|
||||||
|
// Finalize the composition if all results arrived in-place
|
||||||
|
state->accept();
|
||||||
|
},
|
||||||
|
signature, std::move(ownership));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace composition
|
} // namespace composition
|
||||||
|
|||||||
@ -169,28 +169,27 @@ struct is_composition_strategy<composition_strategy_any_tag> // ...
|
|||||||
template <>
|
template <>
|
||||||
struct composition_finalizer<composition_strategy_any_tag> {
|
struct composition_finalizer<composition_strategy_any_tag> {
|
||||||
template <typename Composition>
|
template <typename Composition>
|
||||||
static constexpr auto hint() {
|
static auto finalize(Composition&& composition, util::ownership ownership) {
|
||||||
return decltype(any::result_deducer::deduce(
|
auto signature = decltype(any::result_deducer::deduce(
|
||||||
traversal::container_category_of_t<std::decay_t<Composition>>{},
|
traversal::container_category_of_t<std::decay_t<Composition>>{},
|
||||||
traits::identity<std::decay_t<Composition>>{})){};
|
traits::identity<std::decay_t<Composition>>{})){};
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Composition>
|
return base::attorney::create(
|
||||||
static auto finalize(Composition&& composition) {
|
[composition =
|
||||||
return [composition = std::forward<Composition>(composition)](
|
std::forward<Composition>(composition)](auto&& callback) mutable {
|
||||||
auto&& callback) mutable {
|
|
||||||
|
|
||||||
using submitter_t =
|
using submitter_t =
|
||||||
any::any_result_submitter<std::decay_t<decltype(callback)>>;
|
any::any_result_submitter<std::decay_t<decltype(callback)>>;
|
||||||
|
|
||||||
// Create the submitter which calls the given callback once at the
|
// Create the submitter which calls the given callback once at the
|
||||||
// first callback invocation.
|
// first callback invocation.
|
||||||
auto submitter = std::make_shared<submitter_t>(
|
auto submitter = std::make_shared<submitter_t>(
|
||||||
std::forward<decltype(callback)>(callback));
|
std::forward<decltype(callback)>(callback));
|
||||||
|
|
||||||
traverse_pack(any::continuable_dispatcher<submitter_t>{submitter},
|
traverse_pack(any::continuable_dispatcher<submitter_t>{submitter},
|
||||||
std::move(composition));
|
std::move(composition));
|
||||||
};
|
},
|
||||||
|
signature, std::move(ownership));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace composition
|
} // namespace composition
|
||||||
|
|||||||
@ -134,31 +134,31 @@ struct is_composition_strategy<composition_strategy_seq_tag> // ...
|
|||||||
/// Finalizes the seq logic of a given composition
|
/// Finalizes the seq logic of a given composition
|
||||||
template <>
|
template <>
|
||||||
struct composition_finalizer<composition_strategy_seq_tag> {
|
struct composition_finalizer<composition_strategy_seq_tag> {
|
||||||
template <typename Composition>
|
|
||||||
static constexpr auto hint() {
|
|
||||||
return decltype(aggregated::deduce_hint(std::declval<Composition>())){};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Finalizes the all logic of a given composition
|
/// Finalizes the all logic of a given composition
|
||||||
template <typename Composition>
|
template <typename Composition>
|
||||||
static auto finalize(Composition&& composition) {
|
static auto finalize(Composition&& composition, util::ownership ownership) {
|
||||||
return [composition = std::forward<Composition>(composition)] // ...
|
|
||||||
(auto&& callback) mutable {
|
|
||||||
|
|
||||||
auto boxed = aggregated::box_continuables(std::move(composition));
|
auto result =
|
||||||
|
aggregated::box_continuables(std::forward<Composition>(composition));
|
||||||
|
|
||||||
// The data from which the visitor is constructed in-place
|
auto signature = aggregated::hint_of_data<decltype(result)>();
|
||||||
using data_t =
|
|
||||||
seq::sequential_dispatch_data<std::decay_t<decltype(callback)>,
|
|
||||||
std::decay_t<decltype(boxed)>>;
|
|
||||||
|
|
||||||
// The visitor type
|
return base::attorney::create(
|
||||||
using visitor_t = seq::sequential_dispatch_visitor<data_t>;
|
[result = std::move(result)](auto&& callback) mutable {
|
||||||
|
|
||||||
traverse_pack_async(
|
// The data from which the visitor is constructed in-place
|
||||||
async_traverse_in_place_tag<visitor_t>{},
|
using data_t =
|
||||||
data_t{std::forward<decltype(callback)>(callback), std::move(boxed)});
|
seq::sequential_dispatch_data<std::decay_t<decltype(callback)>,
|
||||||
};
|
std::decay_t<decltype(result)>>;
|
||||||
|
|
||||||
|
// The visitor type
|
||||||
|
using visitor_t = seq::sequential_dispatch_visitor<data_t>;
|
||||||
|
|
||||||
|
traverse_pack_async(async_traverse_in_place_tag<visitor_t>{},
|
||||||
|
data_t{std::forward<decltype(callback)>(callback),
|
||||||
|
std::move(result)});
|
||||||
|
},
|
||||||
|
signature, std::move(ownership));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace composition
|
} // namespace composition
|
||||||
|
|||||||
@ -47,7 +47,7 @@ namespace detail {
|
|||||||
/// The namespace `composition` offers methods to chain continuations together
|
/// The namespace `composition` offers methods to chain continuations together
|
||||||
/// with `all`, `any` or `seq` logic.
|
/// with `all`, `any` or `seq` logic.
|
||||||
namespace composition {
|
namespace composition {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_composition_strategy // ...
|
struct is_composition_strategy // ...
|
||||||
: std::false_type {};
|
: std::false_type {};
|
||||||
|
|
||||||
@ -133,13 +133,8 @@ auto finalize_composition(continuable_base<Data, Strategy>&& continuation) {
|
|||||||
util::ownership ownership = base::attorney::ownership_of(continuation);
|
util::ownership ownership = base::attorney::ownership_of(continuation);
|
||||||
auto composition = base::attorney::consume_data(std::move(continuation));
|
auto composition = base::attorney::consume_data(std::move(continuation));
|
||||||
|
|
||||||
// Retrieve the new signature hint
|
|
||||||
constexpr auto const signature =
|
|
||||||
finalizer::template hint<decltype(composition)>();
|
|
||||||
|
|
||||||
// Return a new continuable which
|
// Return a new continuable which
|
||||||
return base::attorney::create(finalizer::finalize(std::move(composition)),
|
return finalizer::finalize(std::move(composition), std::move(ownership));
|
||||||
signature, std::move(ownership));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A base class from which the continuable may inherit in order to
|
/// A base class from which the continuable may inherit in order to
|
||||||
@ -203,13 +198,7 @@ auto apply_composition(Strategy, Args&&... args) {
|
|||||||
auto composition = map_pack(prepare_continuables{ownership},
|
auto composition = map_pack(prepare_continuables{ownership},
|
||||||
std::make_tuple(std::forward<Args>(args)...));
|
std::make_tuple(std::forward<Args>(args)...));
|
||||||
|
|
||||||
// Retrieve the new signature hint
|
return finalizer::finalize(std::move(composition), std::move(ownership));
|
||||||
constexpr auto const signature =
|
|
||||||
finalizer::template hint<decltype(composition)>();
|
|
||||||
|
|
||||||
// Return a new continuable which
|
|
||||||
return base::attorney::create(finalizer::finalize(std::move(composition)),
|
|
||||||
signature, std::move(ownership));
|
|
||||||
}
|
}
|
||||||
} // namespace composition
|
} // namespace composition
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user