Calculate the connection hint directly from the intermediate result

This commit is contained in:
Denis Blank 2018-03-12 08:25:44 +01:00
parent 49a097660b
commit cd6f7445f0
5 changed files with 78 additions and 126 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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