Skip to content

Commit ad1bb84

Browse files
authored
Add on algorithm (#110)
* 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
1 parent 752882e commit ad1bb84

File tree

13 files changed

+505
-32
lines changed

13 files changed

+505
-32
lines changed

include/beman/execution26/detail/basic_sender.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,15 @@ struct basic_sender : ::beman::execution26::detail::product_type<Tag, Data, Chil
7474
return {::std::forward<Self>(self), ::std::move(receiver)};
7575
}
7676
#endif
77-
#if __cpp_explicit_this_parameter < 202110L
77+
#if __cpp_explicit_this_parameter < 302110L
7878
template <typename Env>
7979
auto
8080
get_completion_signatures(Env&&) && -> ::beman::execution26::detail::completion_signatures_for<basic_sender, Env> {
8181
return {};
8282
}
8383
template <typename Env>
8484
auto get_completion_signatures(
85-
Env&&) const&& -> ::beman::execution26::detail::completion_signatures_for<basic_sender, Env> {
85+
Env&&) const&& -> ::beman::execution26::detail::completion_signatures_for<const basic_sender, Env> {
8686
return {};
8787
}
8888
template <typename Env>
@@ -92,7 +92,7 @@ struct basic_sender : ::beman::execution26::detail::product_type<Tag, Data, Chil
9292
}
9393
template <typename Env>
9494
auto get_completion_signatures(
95-
Env&&) const& -> ::beman::execution26::detail::completion_signatures_for<basic_sender, Env> {
95+
Env&&) const& -> ::beman::execution26::detail::completion_signatures_for<const basic_sender, Env> {
9696
return {};
9797
}
9898
#else

include/beman/execution26/detail/connect.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ namespace beman::execution26::detail {
2323
struct connect_t {
2424
private:
2525
template <typename Sender, typename Receiver>
26-
static auto make_new_sender(Sender&& sender, Receiver&& receiver) noexcept(true) -> decltype(auto) {
26+
static auto make_new_sender(Sender&& sender, Receiver&& receiver)
27+
//-dk:TODO this noexcept needs to get confirmed/fixed
28+
noexcept(true) -> decltype(auto) {
2729
return ::beman::execution26::transform_sender(
2830
decltype(::beman::execution26::detail::get_domain_late(::std::forward<Sender>(sender),
2931
::beman::execution26::get_env(receiver))){},
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// include/beman/execution26/detail/on.hpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#ifndef INCLUDED_INCLUDE_BEMAN_EXECUTION26_DETAIL_ON
5+
#define INCLUDED_INCLUDE_BEMAN_EXECUTION26_DETAIL_ON
6+
7+
#include <beman/execution26/detail/scheduler.hpp>
8+
#include <beman/execution26/detail/sender.hpp>
9+
#include <beman/execution26/detail/sender_adaptor_closure.hpp>
10+
#include <beman/execution26/detail/transform_sender.hpp>
11+
#include <beman/execution26/detail/query_with_default.hpp>
12+
#include <beman/execution26/detail/get_domain.hpp>
13+
#include <beman/execution26/detail/get_domain_early.hpp>
14+
#include <beman/execution26/detail/default_domain.hpp>
15+
#include <beman/execution26/detail/make_sender.hpp>
16+
#include <beman/execution26/detail/product_type.hpp>
17+
#include <beman/execution26/detail/sender_for.hpp>
18+
#include <beman/execution26/detail/join_env.hpp>
19+
#include <beman/execution26/detail/forward_like.hpp>
20+
#include <beman/execution26/detail/fwd_env.hpp>
21+
#include <beman/execution26/detail/sched_env.hpp>
22+
#include <beman/execution26/detail/starts_on.hpp>
23+
#include <beman/execution26/detail/continues_on.hpp>
24+
#include <beman/execution26/detail/write_env.hpp>
25+
#include <utility>
26+
27+
#include <beman/execution26/detail/suppress_push.hpp>
28+
29+
// ----------------------------------------------------------------------------
30+
31+
namespace beman::execution26::detail {
32+
struct on_t : ::beman::execution26::sender_adaptor_closure<on_t> {
33+
template <::beman::execution26::detail::sender_for<on_t> OutSndr, typename Env>
34+
auto transform_env(OutSndr&& out_sndr, Env&& env) const -> decltype(auto) {
35+
auto&& data{out_sndr.template get<1>()};
36+
37+
if constexpr (::beman::execution26::scheduler<decltype(data)>)
38+
return ::beman::execution26::detail::join_env(
39+
::beman::execution26::detail::sched_env(::beman::execution26::detail::forward_like<OutSndr>(data)
40+
41+
),
42+
::beman::execution26::detail::fwd_env(::std::forward<Env>(env)));
43+
else
44+
return std::forward<Env>(env);
45+
}
46+
47+
template <typename>
48+
struct env_needs_get_scheduler {
49+
using sender_concept = ::beman::execution26::sender_t;
50+
template <typename Env>
51+
auto get_completion_signatures(Env&&) const {
52+
return env_needs_get_scheduler<Env>{};
53+
}
54+
};
55+
56+
template <::beman::execution26::detail::sender_for<on_t> OutSndr, typename Env>
57+
auto transform_sender(OutSndr&& out_sndr, Env&& env) const -> decltype(auto) {
58+
struct not_a_scheduler {};
59+
auto&& [_, data, child] = out_sndr;
60+
61+
if constexpr (::beman::execution26::scheduler<decltype(data)>) {
62+
auto sch{::beman::execution26::detail::query_with_default(
63+
::beman::execution26::get_scheduler, env, not_a_scheduler{})};
64+
if constexpr (::std::same_as<not_a_scheduler, decltype(sch)>) {
65+
return env_needs_get_scheduler<Env>{};
66+
} else {
67+
return ::beman::execution26::continues_on(
68+
::beman::execution26::starts_on(::beman::execution26::detail::forward_like<OutSndr>(data),
69+
::beman::execution26::detail::forward_like<OutSndr>(child)),
70+
::std::move(sch));
71+
}
72+
} else {
73+
auto& [sch, closure] = data;
74+
auto orig_sch{::beman::execution26::detail::query_with_default(
75+
::beman::execution26::get_completion_scheduler<::beman::execution26::set_value_t>,
76+
::beman::execution26::get_env(child),
77+
::beman::execution26::detail::query_with_default(
78+
::beman::execution26::get_scheduler, env, not_a_scheduler{}))};
79+
80+
if constexpr (::std::same_as<not_a_scheduler, decltype(orig_sch)>) {
81+
return env_needs_get_scheduler<Env>{};
82+
} else {
83+
return ::beman::execution26::detail::write_env(
84+
::beman::execution26::continues_on(
85+
::beman::execution26::detail::forward_like<OutSndr>(closure)(
86+
::beman::execution26::continues_on(
87+
::beman::execution26::detail::write_env(
88+
::beman::execution26::detail::forward_like<OutSndr>(child),
89+
::beman::execution26::detail::sched_env(orig_sch)),
90+
sch)),
91+
orig_sch),
92+
::beman::execution26::detail::sched_env(env));
93+
}
94+
}
95+
}
96+
97+
template <::beman::execution26::scheduler Sch, ::beman::execution26::sender Sndr>
98+
requires ::beman::execution26::detail::is_sender_adaptor_closure<Sndr>
99+
auto operator()(Sch&&, Sndr&&) const -> void =
100+
BEMAN_EXECUTION26_DELETE("on(sch, sndr) requires that sndr isn't both a sender and sender adaptor closure");
101+
102+
template <::beman::execution26::scheduler Sch,
103+
::beman::execution26::sender Sndr,
104+
::beman::execution26::detail::is_sender_adaptor_closure Closure>
105+
requires ::beman::execution26::detail::is_sender_adaptor_closure<Sndr>
106+
auto operator()(Sndr&&, Sch&&, Closure&&) const -> void =
107+
BEMAN_EXECUTION26_DELETE("on(sch, sndr) requires that sndr isn't both a sender and sender adaptor closure");
108+
109+
template <::beman::execution26::scheduler Sch, ::beman::execution26::sender Sndr>
110+
auto operator()(Sch&& sch, Sndr&& sndr) const {
111+
auto domain{::beman::execution26::detail::query_with_default(
112+
::beman::execution26::get_domain, sch, ::beman::execution26::default_domain{})};
113+
return ::beman::execution26::transform_sender(
114+
domain,
115+
::beman::execution26::detail::make_sender(*this, ::std::forward<Sch>(sch), ::std::forward<Sndr>(sndr)));
116+
}
117+
template <::beman::execution26::scheduler Sch,
118+
::beman::execution26::sender Sndr,
119+
::beman::execution26::detail::is_sender_adaptor_closure Closure>
120+
auto operator()(Sndr&& sndr, Sch&& sch, Closure&& closure) const {
121+
auto domain{::beman::execution26::detail::get_domain_early(sndr)};
122+
return ::beman::execution26::transform_sender(
123+
domain,
124+
::beman::execution26::detail::make_sender(
125+
*this,
126+
::beman::execution26::detail::product_type{::std::forward<Sch>(sch), ::std::forward<Closure>(closure)},
127+
::std::forward<Sndr>(sndr)));
128+
}
129+
template <::beman::execution26::scheduler Sch, ::beman::execution26::detail::is_sender_adaptor_closure Closure>
130+
auto operator()(Sch&& sch, Closure&& closure) const {
131+
return ::beman::execution26::detail::sender_adaptor{
132+
*this, ::std::forward<Sch>(sch), ::std::forward<Closure>(closure)};
133+
}
134+
};
135+
136+
#if 0
137+
template <typename Data, typename Sender, typename Env>
138+
struct completion_signatures_for_impl<
139+
::beman::execution26::detail::basic_sender<::beman::execution26::detail::on_t, Data, Sender>,
140+
Env> {
141+
//-dk:TODO pick up scheduler errors and merge them in?
142+
using type =
143+
#if 0
144+
::beman::execution26::detail::meta::combine<
145+
::beman::execution26::completion_signatures_of_t<Sender, Env>,
146+
::beman::execution26::completion_signatures<::beman::execution26::set_error_t(::std::exception_ptr)>
147+
>
148+
#else
149+
::beman::execution26::completion_signatures<
150+
::beman::execution26::set_value_t(),
151+
::beman::execution26::set_error_t(::std::exception_ptr)
152+
>
153+
#endif
154+
;
155+
};
156+
#endif
157+
158+
} // namespace beman::execution26::detail
159+
160+
namespace beman::execution26 {
161+
using on_t = ::beman::execution26::detail::on_t;
162+
inline constexpr ::beman::execution26::on_t on{};
163+
} // namespace beman::execution26
164+
165+
// ----------------------------------------------------------------------------
166+
167+
#include <beman/execution26/detail/suppress_pop.hpp>
168+
169+
#endif

include/beman/execution26/detail/product_type.hpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
// ----------------------------------------------------------------------------
1111

1212
namespace beman::execution26::detail {
13-
template <::std::size_t, typename T>
13+
14+
template <::std::size_t I, typename T>
1415
struct product_type_element {
1516
T value;
1617
auto operator==(const product_type_element&) const -> bool = default;
@@ -23,6 +24,7 @@ template <::std::size_t... I, typename... T>
2324
struct product_type_base<::std::index_sequence<I...>, T...>
2425
: ::beman::execution26::detail::product_type_element<I, T>... {
2526
static constexpr ::std::size_t size() { return sizeof...(T); }
27+
static constexpr bool is_product_type{true};
2628

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

69+
template <typename T>
70+
concept is_product_type_c = requires(const T& t) { T::is_product_type; };
71+
6772
template <typename... T>
6873
struct product_type : ::beman::execution26::detail::product_type_base<::std::index_sequence_for<T...>, T...> {
6974
template <typename Allocator, typename Product, std::size_t... I>
@@ -108,13 +113,14 @@ constexpr auto is_product_type(const ::beman::execution26::detail::product_type<
108113
} // namespace beman::execution26::detail
109114

110115
namespace std {
111-
template <typename... T>
112-
struct tuple_size<::beman::execution26::detail::product_type<T...>>
113-
: ::std::integral_constant<std::size_t, sizeof...(T)> {};
114-
template <::std::size_t I, typename... T>
115-
struct tuple_element<I, ::beman::execution26::detail::product_type<T...>> {
116-
using type =
117-
::std::decay_t<decltype(::std::declval<::beman::execution26::detail::product_type<T...>>().template get<I>())>;
116+
template <typename T>
117+
requires ::beman::execution26::detail::is_product_type_c<T>
118+
struct tuple_size<T> : ::std::integral_constant<std::size_t, T::size()> {};
119+
120+
template <::std::size_t I, typename T>
121+
requires ::beman::execution26::detail::is_product_type_c<T>
122+
struct tuple_element<I, T> {
123+
using type = ::std::decay_t<decltype(::std::declval<T>().template get<I>())>;
118124
};
119125
} // namespace std
120126

include/beman/execution26/detail/schedule_from.hpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SCHEDULE_FROM
66

77
#include <beman/execution26/detail/child_type.hpp>
8+
#include <beman/execution26/detail/meta_combine.hpp>
89
#include <beman/execution26/detail/completion_signatures_of_t.hpp>
910
#include <beman/execution26/detail/connect.hpp>
1011
#include <beman/execution26/detail/decayed_tuple.hpp>
1112
#include <beman/execution26/detail/default_domain.hpp>
1213
#include <beman/execution26/detail/default_impls.hpp>
14+
#include <beman/execution26/detail/error_types_of_t.hpp>
1315
#include <beman/execution26/detail/env_of_t.hpp>
1416
#include <beman/execution26/detail/fwd_env.hpp>
1517
#include <beman/execution26/detail/get_domain.hpp>
@@ -144,10 +146,15 @@ struct impls_for<::beman::execution26::detail::schedule_from_t> : ::beman::execu
144146
::std::monostate,
145147
::beman::execution26::detail::meta::transform<
146148
::beman::execution26::detail::as_tuple_t,
147-
::beman::execution26::detail::meta::to<::std::variant,
148-
::beman::execution26::completion_signatures_of_t<
149-
::beman::execution26::detail::child_type<Sender>,
150-
::beman::execution26::env_of_t<Receiver>>>>>>;
149+
::beman::execution26::detail::meta::to<
150+
::std::variant,
151+
::beman::execution26::detail::meta::combine<
152+
::beman::execution26::completion_signatures_of_t<
153+
::beman::execution26::detail::child_type<Sender>,
154+
::beman::execution26::env_of_t<Receiver>>,
155+
//-dk:TODO get proper error completion signatures
156+
::beman::execution26::completion_signatures<::beman::execution26::set_error_t(
157+
::std::exception_ptr)>>>>>>;
151158

152159
return state_type<Receiver, sched_t, variant_t>(sch, receiver);
153160
}};
@@ -176,8 +183,15 @@ template <typename Scheduler, typename Sender, typename Env>
176183
struct completion_signatures_for_impl<
177184
::beman::execution26::detail::basic_sender<::beman::execution26::detail::schedule_from_t, Scheduler, Sender>,
178185
Env> {
179-
using type =
180-
decltype(::beman::execution26::get_completion_signatures(::std::declval<Sender>(), ::std::declval<Env>()));
186+
using scheduler_sender = decltype(::beman::execution26::schedule(::std::declval<Scheduler>()));
187+
template <typename... E>
188+
using as_set_error = ::beman::execution26::completion_signatures<::beman::execution26::set_error_t(E)...>;
189+
using type = ::beman::execution26::detail::meta::combine<
190+
decltype(::beman::execution26::get_completion_signatures(::std::declval<Sender>(), ::std::declval<Env>())),
191+
::beman::execution26::error_types_of_t<scheduler_sender, Env, as_set_error>,
192+
::beman::execution26::completion_signatures<::beman::execution26::set_error_t(
193+
::std::exception_ptr)> //-dk:TODO this one should be deduced
194+
>;
181195
};
182196
} // namespace beman::execution26::detail
183197

include/beman/execution26/detail/sender_adaptor_closure.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,16 @@ namespace beman::execution26 {
2020
template <typename>
2121
struct sender_adaptor_closure : ::beman::execution26::detail::pipeable::sender_adaptor_closure_base {};
2222
// NOLINTEND(bugprone-crtp-constructor-accessibility)
23+
2324
} // namespace beman::execution26
2425

26+
namespace beman::execution26::detail {
27+
template <typename Closure>
28+
concept is_sender_adaptor_closure =
29+
::std::derived_from<::std::decay_t<Closure>,
30+
::beman::execution26::sender_adaptor_closure<::std::decay_t<Closure>>>;
31+
}
32+
2533
namespace beman::execution26::detail::pipeable {
2634
template <::beman::execution26::sender Sender, typename Adaptor>
2735
requires(not::beman::execution26::sender<Adaptor>) &&

0 commit comments

Comments
 (0)