Skip to content

Commit

Permalink
Add on algorithm (#110)
Browse files Browse the repository at this point in the history
* started to implement on

* added structured binding support for types derived from product type

* added on algorithm and applies various fixes

* fix a silly formatting error

* fixed a few warnings
  • Loading branch information
dietmarkuehl authored Jan 4, 2025
1 parent 752882e commit ad1bb84
Show file tree
Hide file tree
Showing 13 changed files with 505 additions and 32 deletions.
6 changes: 3 additions & 3 deletions include/beman/execution26/detail/basic_sender.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ struct basic_sender : ::beman::execution26::detail::product_type<Tag, Data, Chil
return {::std::forward<Self>(self), ::std::move(receiver)};
}
#endif
#if __cpp_explicit_this_parameter < 202110L
#if __cpp_explicit_this_parameter < 302110L
template <typename Env>
auto
get_completion_signatures(Env&&) && -> ::beman::execution26::detail::completion_signatures_for<basic_sender, Env> {
return {};
}
template <typename Env>
auto get_completion_signatures(
Env&&) const&& -> ::beman::execution26::detail::completion_signatures_for<basic_sender, Env> {
Env&&) const&& -> ::beman::execution26::detail::completion_signatures_for<const basic_sender, Env> {
return {};
}
template <typename Env>
Expand All @@ -92,7 +92,7 @@ struct basic_sender : ::beman::execution26::detail::product_type<Tag, Data, Chil
}
template <typename Env>
auto get_completion_signatures(
Env&&) const& -> ::beman::execution26::detail::completion_signatures_for<basic_sender, Env> {
Env&&) const& -> ::beman::execution26::detail::completion_signatures_for<const basic_sender, Env> {
return {};
}
#else
Expand Down
4 changes: 3 additions & 1 deletion include/beman/execution26/detail/connect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ namespace beman::execution26::detail {
struct connect_t {
private:
template <typename Sender, typename Receiver>
static auto make_new_sender(Sender&& sender, Receiver&& receiver) noexcept(true) -> decltype(auto) {
static auto make_new_sender(Sender&& sender, Receiver&& receiver)
//-dk:TODO this noexcept needs to get confirmed/fixed
noexcept(true) -> decltype(auto) {
return ::beman::execution26::transform_sender(
decltype(::beman::execution26::detail::get_domain_late(::std::forward<Sender>(sender),
::beman::execution26::get_env(receiver))){},
Expand Down
169 changes: 169 additions & 0 deletions include/beman/execution26/detail/on.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// include/beman/execution26/detail/on.hpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef INCLUDED_INCLUDE_BEMAN_EXECUTION26_DETAIL_ON
#define INCLUDED_INCLUDE_BEMAN_EXECUTION26_DETAIL_ON

#include <beman/execution26/detail/scheduler.hpp>
#include <beman/execution26/detail/sender.hpp>
#include <beman/execution26/detail/sender_adaptor_closure.hpp>
#include <beman/execution26/detail/transform_sender.hpp>
#include <beman/execution26/detail/query_with_default.hpp>
#include <beman/execution26/detail/get_domain.hpp>
#include <beman/execution26/detail/get_domain_early.hpp>
#include <beman/execution26/detail/default_domain.hpp>
#include <beman/execution26/detail/make_sender.hpp>
#include <beman/execution26/detail/product_type.hpp>
#include <beman/execution26/detail/sender_for.hpp>
#include <beman/execution26/detail/join_env.hpp>
#include <beman/execution26/detail/forward_like.hpp>
#include <beman/execution26/detail/fwd_env.hpp>
#include <beman/execution26/detail/sched_env.hpp>
#include <beman/execution26/detail/starts_on.hpp>
#include <beman/execution26/detail/continues_on.hpp>
#include <beman/execution26/detail/write_env.hpp>
#include <utility>

#include <beman/execution26/detail/suppress_push.hpp>

// ----------------------------------------------------------------------------

namespace beman::execution26::detail {
struct on_t : ::beman::execution26::sender_adaptor_closure<on_t> {
template <::beman::execution26::detail::sender_for<on_t> OutSndr, typename Env>
auto transform_env(OutSndr&& out_sndr, Env&& env) const -> decltype(auto) {
auto&& data{out_sndr.template get<1>()};

if constexpr (::beman::execution26::scheduler<decltype(data)>)
return ::beman::execution26::detail::join_env(
::beman::execution26::detail::sched_env(::beman::execution26::detail::forward_like<OutSndr>(data)

),
::beman::execution26::detail::fwd_env(::std::forward<Env>(env)));
else
return std::forward<Env>(env);
}

template <typename>
struct env_needs_get_scheduler {
using sender_concept = ::beman::execution26::sender_t;
template <typename Env>
auto get_completion_signatures(Env&&) const {
return env_needs_get_scheduler<Env>{};
}
};

template <::beman::execution26::detail::sender_for<on_t> OutSndr, typename Env>
auto transform_sender(OutSndr&& out_sndr, Env&& env) const -> decltype(auto) {
struct not_a_scheduler {};
auto&& [_, data, child] = out_sndr;

if constexpr (::beman::execution26::scheduler<decltype(data)>) {
auto sch{::beman::execution26::detail::query_with_default(
::beman::execution26::get_scheduler, env, not_a_scheduler{})};
if constexpr (::std::same_as<not_a_scheduler, decltype(sch)>) {
return env_needs_get_scheduler<Env>{};
} else {
return ::beman::execution26::continues_on(
::beman::execution26::starts_on(::beman::execution26::detail::forward_like<OutSndr>(data),
::beman::execution26::detail::forward_like<OutSndr>(child)),
::std::move(sch));
}
} else {
auto& [sch, closure] = data;
auto orig_sch{::beman::execution26::detail::query_with_default(
::beman::execution26::get_completion_scheduler<::beman::execution26::set_value_t>,
::beman::execution26::get_env(child),
::beman::execution26::detail::query_with_default(
::beman::execution26::get_scheduler, env, not_a_scheduler{}))};

if constexpr (::std::same_as<not_a_scheduler, decltype(orig_sch)>) {
return env_needs_get_scheduler<Env>{};
} else {
return ::beman::execution26::detail::write_env(
::beman::execution26::continues_on(
::beman::execution26::detail::forward_like<OutSndr>(closure)(
::beman::execution26::continues_on(
::beman::execution26::detail::write_env(
::beman::execution26::detail::forward_like<OutSndr>(child),
::beman::execution26::detail::sched_env(orig_sch)),
sch)),
orig_sch),
::beman::execution26::detail::sched_env(env));
}
}
}

template <::beman::execution26::scheduler Sch, ::beman::execution26::sender Sndr>
requires ::beman::execution26::detail::is_sender_adaptor_closure<Sndr>
auto operator()(Sch&&, Sndr&&) const -> void =
BEMAN_EXECUTION26_DELETE("on(sch, sndr) requires that sndr isn't both a sender and sender adaptor closure");

template <::beman::execution26::scheduler Sch,
::beman::execution26::sender Sndr,
::beman::execution26::detail::is_sender_adaptor_closure Closure>
requires ::beman::execution26::detail::is_sender_adaptor_closure<Sndr>
auto operator()(Sndr&&, Sch&&, Closure&&) const -> void =
BEMAN_EXECUTION26_DELETE("on(sch, sndr) requires that sndr isn't both a sender and sender adaptor closure");

template <::beman::execution26::scheduler Sch, ::beman::execution26::sender Sndr>
auto operator()(Sch&& sch, Sndr&& sndr) const {
auto domain{::beman::execution26::detail::query_with_default(
::beman::execution26::get_domain, sch, ::beman::execution26::default_domain{})};
return ::beman::execution26::transform_sender(
domain,
::beman::execution26::detail::make_sender(*this, ::std::forward<Sch>(sch), ::std::forward<Sndr>(sndr)));
}
template <::beman::execution26::scheduler Sch,
::beman::execution26::sender Sndr,
::beman::execution26::detail::is_sender_adaptor_closure Closure>
auto operator()(Sndr&& sndr, Sch&& sch, Closure&& closure) const {
auto domain{::beman::execution26::detail::get_domain_early(sndr)};
return ::beman::execution26::transform_sender(
domain,
::beman::execution26::detail::make_sender(
*this,
::beman::execution26::detail::product_type{::std::forward<Sch>(sch), ::std::forward<Closure>(closure)},
::std::forward<Sndr>(sndr)));
}
template <::beman::execution26::scheduler Sch, ::beman::execution26::detail::is_sender_adaptor_closure Closure>
auto operator()(Sch&& sch, Closure&& closure) const {
return ::beman::execution26::detail::sender_adaptor{
*this, ::std::forward<Sch>(sch), ::std::forward<Closure>(closure)};
}
};

#if 0
template <typename Data, typename Sender, typename Env>
struct completion_signatures_for_impl<
::beman::execution26::detail::basic_sender<::beman::execution26::detail::on_t, Data, Sender>,
Env> {
//-dk:TODO pick up scheduler errors and merge them in?
using type =
#if 0
::beman::execution26::detail::meta::combine<
::beman::execution26::completion_signatures_of_t<Sender, Env>,
::beman::execution26::completion_signatures<::beman::execution26::set_error_t(::std::exception_ptr)>
>
#else
::beman::execution26::completion_signatures<
::beman::execution26::set_value_t(),
::beman::execution26::set_error_t(::std::exception_ptr)
>
#endif
;
};
#endif

} // namespace beman::execution26::detail

namespace beman::execution26 {
using on_t = ::beman::execution26::detail::on_t;
inline constexpr ::beman::execution26::on_t on{};
} // namespace beman::execution26

// ----------------------------------------------------------------------------

#include <beman/execution26/detail/suppress_pop.hpp>

#endif
22 changes: 14 additions & 8 deletions include/beman/execution26/detail/product_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
// ----------------------------------------------------------------------------

namespace beman::execution26::detail {
template <::std::size_t, typename T>

template <::std::size_t I, typename T>
struct product_type_element {
T value;
auto operator==(const product_type_element&) const -> bool = default;
Expand All @@ -23,6 +24,7 @@ template <::std::size_t... I, typename... T>
struct product_type_base<::std::index_sequence<I...>, T...>
: ::beman::execution26::detail::product_type_element<I, T>... {
static constexpr ::std::size_t size() { return sizeof...(T); }
static constexpr bool is_product_type{true};

template <::std::size_t J, typename S>
static auto element_get(::beman::execution26::detail::product_type_element<J, S>& self) noexcept -> S& {
Expand Down Expand Up @@ -64,6 +66,9 @@ struct product_type_base<::std::index_sequence<I...>, T...>
auto operator==(const product_type_base&) const -> bool = default;
};

template <typename T>
concept is_product_type_c = requires(const T& t) { T::is_product_type; };

template <typename... T>
struct product_type : ::beman::execution26::detail::product_type_base<::std::index_sequence_for<T...>, T...> {
template <typename Allocator, typename Product, std::size_t... I>
Expand Down Expand Up @@ -108,13 +113,14 @@ constexpr auto is_product_type(const ::beman::execution26::detail::product_type<
} // namespace beman::execution26::detail

namespace std {
template <typename... T>
struct tuple_size<::beman::execution26::detail::product_type<T...>>
: ::std::integral_constant<std::size_t, sizeof...(T)> {};
template <::std::size_t I, typename... T>
struct tuple_element<I, ::beman::execution26::detail::product_type<T...>> {
using type =
::std::decay_t<decltype(::std::declval<::beman::execution26::detail::product_type<T...>>().template get<I>())>;
template <typename T>
requires ::beman::execution26::detail::is_product_type_c<T>
struct tuple_size<T> : ::std::integral_constant<std::size_t, T::size()> {};

template <::std::size_t I, typename T>
requires ::beman::execution26::detail::is_product_type_c<T>
struct tuple_element<I, T> {
using type = ::std::decay_t<decltype(::std::declval<T>().template get<I>())>;
};
} // namespace std

Expand Down
26 changes: 20 additions & 6 deletions include/beman/execution26/detail/schedule_from.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SCHEDULE_FROM

#include <beman/execution26/detail/child_type.hpp>
#include <beman/execution26/detail/meta_combine.hpp>
#include <beman/execution26/detail/completion_signatures_of_t.hpp>
#include <beman/execution26/detail/connect.hpp>
#include <beman/execution26/detail/decayed_tuple.hpp>
#include <beman/execution26/detail/default_domain.hpp>
#include <beman/execution26/detail/default_impls.hpp>
#include <beman/execution26/detail/error_types_of_t.hpp>
#include <beman/execution26/detail/env_of_t.hpp>
#include <beman/execution26/detail/fwd_env.hpp>
#include <beman/execution26/detail/get_domain.hpp>
Expand Down Expand Up @@ -144,10 +146,15 @@ struct impls_for<::beman::execution26::detail::schedule_from_t> : ::beman::execu
::std::monostate,
::beman::execution26::detail::meta::transform<
::beman::execution26::detail::as_tuple_t,
::beman::execution26::detail::meta::to<::std::variant,
::beman::execution26::completion_signatures_of_t<
::beman::execution26::detail::child_type<Sender>,
::beman::execution26::env_of_t<Receiver>>>>>>;
::beman::execution26::detail::meta::to<
::std::variant,
::beman::execution26::detail::meta::combine<
::beman::execution26::completion_signatures_of_t<
::beman::execution26::detail::child_type<Sender>,
::beman::execution26::env_of_t<Receiver>>,
//-dk:TODO get proper error completion signatures
::beman::execution26::completion_signatures<::beman::execution26::set_error_t(
::std::exception_ptr)>>>>>>;

return state_type<Receiver, sched_t, variant_t>(sch, receiver);
}};
Expand Down Expand Up @@ -176,8 +183,15 @@ template <typename Scheduler, typename Sender, typename Env>
struct completion_signatures_for_impl<
::beman::execution26::detail::basic_sender<::beman::execution26::detail::schedule_from_t, Scheduler, Sender>,
Env> {
using type =
decltype(::beman::execution26::get_completion_signatures(::std::declval<Sender>(), ::std::declval<Env>()));
using scheduler_sender = decltype(::beman::execution26::schedule(::std::declval<Scheduler>()));
template <typename... E>
using as_set_error = ::beman::execution26::completion_signatures<::beman::execution26::set_error_t(E)...>;
using type = ::beman::execution26::detail::meta::combine<
decltype(::beman::execution26::get_completion_signatures(::std::declval<Sender>(), ::std::declval<Env>())),
::beman::execution26::error_types_of_t<scheduler_sender, Env, as_set_error>,
::beman::execution26::completion_signatures<::beman::execution26::set_error_t(
::std::exception_ptr)> //-dk:TODO this one should be deduced
>;
};
} // namespace beman::execution26::detail

Expand Down
8 changes: 8 additions & 0 deletions include/beman/execution26/detail/sender_adaptor_closure.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,16 @@ namespace beman::execution26 {
template <typename>
struct sender_adaptor_closure : ::beman::execution26::detail::pipeable::sender_adaptor_closure_base {};
// NOLINTEND(bugprone-crtp-constructor-accessibility)

} // namespace beman::execution26

namespace beman::execution26::detail {
template <typename Closure>
concept is_sender_adaptor_closure =
::std::derived_from<::std::decay_t<Closure>,
::beman::execution26::sender_adaptor_closure<::std::decay_t<Closure>>>;
}

namespace beman::execution26::detail::pipeable {
template <::beman::execution26::sender Sender, typename Adaptor>
requires(not::beman::execution26::sender<Adaptor>) &&
Expand Down
Loading

0 comments on commit ad1bb84

Please sign in to comment.