Skip to content

Commit a48cdba

Browse files
authored
Implement dependent_sender (#255)
* Implement `dependent_sender` * Refactor `basic_sender::get_completion_signatures` to support `dependent_sender` * Fix CI error
1 parent d427c7d commit a48cdba

14 files changed

Lines changed: 200 additions & 71 deletions

File tree

include/beman/execution/detail/basic_sender.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import beman.execution.detail.completion_signatures_for;
1717
import beman.execution.detail.connect;
1818
import beman.execution.detail.connect_all;
1919
import beman.execution.detail.decays_to;
20+
import beman.execution.detail.dependent_sender;
2021
import beman.execution.detail.get_completion_signatures;
2122
import beman.execution.detail.impls_for;
2223
import beman.execution.detail.product_type;
@@ -28,6 +29,7 @@ import beman.execution.detail.sender_decompose;
2829
#include <beman/execution/detail/completion_signatures_for.hpp>
2930
#include <beman/execution/detail/connect.hpp>
3031
#include <beman/execution/detail/decays_to.hpp>
32+
#include <beman/execution/detail/dependent_sender.hpp>
3133
#include <beman/execution/detail/get_completion_signatures.hpp>
3234
#include <beman/execution/detail/impls_for.hpp>
3335
#include <beman/execution/detail/product_type.hpp>
@@ -110,6 +112,7 @@ struct basic_sender : ::beman::execution::detail::product_type<Tag, Data, Child.
110112
}
111113
#endif
112114
template <::beman::execution::detail::decays_to<basic_sender> Self, typename... Env>
115+
requires(sizeof...(Env) == 1) || (... && !::beman::execution::dependent_sender<Child>)
113116
static consteval auto get_completion_signatures() noexcept {
114117
if constexpr (requires { Tag::template get_completion_signatures<Self, Env...>(); })
115118
return Tag::template get_completion_signatures<Self, Env...>();

include/beman/execution/detail/common.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@
1717
#define BEMAN_SPECIALIZE_EXPORT template <>
1818
#endif
1919

20+
#define BEMAN_EXECUTION_TRY_EVAL(rcvr, expr) \
21+
do { \
22+
try { \
23+
(expr); \
24+
} catch (...) { \
25+
if constexpr (!noexcept((expr))) { \
26+
::beman::execution::set_error(::std::move((rcvr)), ::std::current_exception()); \
27+
} \
28+
} \
29+
} while (false)
30+
2031
// ----------------------------------------------------------------------------
2132
/*!
2233
* \mainpage Asynchronous Operation Support
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// include/beman/execution/detail/dependent_sender.hpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#ifndef INCLUDED_BEMAN_EXECUTION_DETAIL_DEPENDENT_SENDER
5+
#define INCLUDED_BEMAN_EXECUTION_DETAIL_DEPENDENT_SENDER
6+
7+
#include <beman/execution/detail/common.hpp>
8+
#ifdef BEMAN_HAS_IMPORT_STD
9+
import std;
10+
#else
11+
#include <concepts>
12+
#endif
13+
#ifdef BEMAN_HAS_MODULES
14+
import beman.execution.detail.get_completion_signatures;
15+
import beman.execution.detail.sender;
16+
#else
17+
#include <beman/execution/detail/get_completion_signatures.hpp>
18+
#include <beman/execution/detail/sender.hpp>
19+
#endif
20+
21+
// ----------------------------------------------------------------------------
22+
23+
namespace beman::execution::detail {
24+
template <auto>
25+
auto non_dependent_sender_helper() noexcept -> void {}
26+
27+
template <typename Sender>
28+
concept non_dependent_sender = ::beman::execution::sender<Sender> && requires {
29+
::beman::execution::detail::non_dependent_sender_helper<::beman::execution::get_completion_signatures<Sender>()>();
30+
};
31+
} // namespace beman::execution::detail
32+
33+
namespace beman::execution {
34+
template <typename Sender>
35+
concept dependent_sender =
36+
::beman::execution::sender<Sender> && !::beman::execution::detail::non_dependent_sender<Sender>;
37+
} // namespace beman::execution
38+
39+
// ----------------------------------------------------------------------------
40+
41+
#endif // INCLUDED_BEMAN_EXECUTION_DETAIL_DEPENDENT_SENDER

include/beman/execution/detail/into_variant.hpp

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,17 @@ import beman.execution.detail.completion_signatures;
2020
import beman.execution.detail.completion_signatures_for;
2121
import beman.execution.detail.decayed_tuple;
2222
import beman.execution.detail.default_impls;
23+
import beman.execution.detail.dependent_sender;
24+
import beman.execution.detail.dependent_sender_error;
25+
import beman.execution.detail.env;
2326
import beman.execution.detail.env_of_t;
2427
import beman.execution.detail.error_types_of_t;
2528
import beman.execution.detail.get_domain_early;
2629
import beman.execution.detail.impls_for;
2730
import beman.execution.detail.make_sender;
2831
import beman.execution.detail.meta.combine;
2932
import beman.execution.detail.sender;
33+
import beman.execution.detail.sender_adaptor_closure;
3034
import beman.execution.detail.sends_stopped;
3135
import beman.execution.detail.set_error;
3236
import beman.execution.detail.set_stopped;
@@ -39,13 +43,17 @@ import beman.execution.detail.variant_or_empty;
3943
#include <beman/execution/detail/completion_signatures_for.hpp>
4044
#include <beman/execution/detail/decayed_tuple.hpp>
4145
#include <beman/execution/detail/default_impls.hpp>
46+
#include <beman/execution/detail/dependent_sender.hpp>
47+
#include <beman/execution/detail/dependent_sender_error.hpp>
48+
#include <beman/execution/detail/env.hpp>
4249
#include <beman/execution/detail/env_of_t.hpp>
4350
#include <beman/execution/detail/error_types_of_t.hpp>
4451
#include <beman/execution/detail/get_domain_early.hpp>
4552
#include <beman/execution/detail/impls_for.hpp>
4653
#include <beman/execution/detail/make_sender.hpp>
4754
#include <beman/execution/detail/meta_combine.hpp>
4855
#include <beman/execution/detail/sender.hpp>
56+
#include <beman/execution/detail/sender_adaptor_closure.hpp>
4957
#include <beman/execution/detail/sends_stopped.hpp>
5058
#include <beman/execution/detail/set_error.hpp>
5159
#include <beman/execution/detail/set_value.hpp>
@@ -56,25 +64,25 @@ import beman.execution.detail.variant_or_empty;
5664
// ----------------------------------------------------------------------------
5765

5866
namespace beman::execution::detail {
59-
struct into_variant_t {
67+
struct into_variant_t : ::beman::execution::sender_adaptor_closure<into_variant_t> {
6068
template <::beman::execution::sender Sender>
6169
auto operator()(Sender&& sender) const {
62-
// auto domain{::beman::execution::detail::get_domain_early(sender)};
63-
//(void)domain;
64-
return ::beman::execution::detail::make_sender(*this, {}, ::std::forward<Sender>(sender));
65-
// return ::beman::execution::transform_sender(
66-
// ::std::move(domain),
67-
// ::beman::execution::detail::make_sender(*this, {}, ::std::forward<Sender>(sender))
68-
//);
70+
return ::beman::execution::transform_sender(
71+
::beman::execution::detail::get_domain_early(sender),
72+
::beman::execution::detail::make_sender(*this, {}, ::std::forward<Sender>(sender)));
6973
}
7074

75+
auto operator()() const noexcept { return ::beman::execution::detail::make_sender_adaptor(*this); }
76+
7177
private:
7278
template <typename... E>
7379
using make_error_types = ::beman::execution::completion_signatures<::beman::execution::set_error_t(E)...>;
7480

7581
private:
76-
template <typename, typename>
82+
template <typename, typename...>
7783
struct get_signatures;
84+
template <typename Sender>
85+
struct get_signatures<Sender> : get_signatures<Sender, ::beman::execution::env<>> {};
7886
template <::beman::execution::sender Child, typename State, typename Env>
7987
struct get_signatures<
8088
::beman::execution::detail::basic_sender<::beman::execution::detail::into_variant_t, State, Child>,
@@ -99,9 +107,9 @@ struct into_variant_t {
99107
};
100108

101109
public:
102-
template <::beman::execution::sender Sender, typename Env>
110+
template <::beman::execution::sender Sender, typename... Env>
103111
static consteval auto get_completion_signatures() {
104-
return get_signatures<::std::remove_cvref_t<Sender>, Env>::get();
112+
return get_signatures<::std::remove_cvref_t<Sender>, Env...>::get();
105113
}
106114
struct impls_for : ::beman::execution::detail::default_impls {
107115
struct get_state_impl {
@@ -119,14 +127,14 @@ struct into_variant_t {
119127
if constexpr (::std::same_as<Tag, ::beman::execution::set_value_t>) {
120128
using variant_type = typename State::type;
121129
using tuple_type = ::beman::execution::detail::decayed_tuple<Args...>;
122-
try {
123-
if constexpr (sizeof...(Args) == 0u)
124-
::beman::execution::set_value(::std::move(receiver));
125-
else
130+
if constexpr (std::same_as<variant_type, ::beman::execution::detail::empty_variant>) {
131+
static_assert(sizeof...(Args) == 0);
132+
BEMAN_EXECUTION_TRY_EVAL(receiver, ::beman::execution::set_value(std::move(receiver)));
133+
} else {
134+
BEMAN_EXECUTION_TRY_EVAL(
135+
receiver,
126136
::beman::execution::set_value(::std::move(receiver),
127-
variant_type(tuple_type{::std::forward<Args>(args)...}));
128-
} catch (...) {
129-
::beman::execution::set_error(::std::move(receiver), ::std::current_exception());
137+
variant_type(tuple_type{::std::forward<Args>(args)...})));
130138
}
131139
} else {
132140
Tag()(::std::move(receiver), ::std::forward<Args>(args)...);

include/beman/execution/detail/read_env.hpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import beman.execution.detail.basic_sender;
1717
import beman.execution.detail.completion_signatures;
1818
import beman.execution.detail.completion_signatures_for;
1919
import beman.execution.detail.default_impls;
20+
import beman.execution.detail.env_of_t;
2021
import beman.execution.detail.get_env;
2122
import beman.execution.detail.impls_for;
2223
import beman.execution.detail.make_sender;
@@ -27,6 +28,7 @@ import beman.execution.detail.set_value;
2728
#include <beman/execution/detail/completion_signatures.hpp>
2829
#include <beman/execution/detail/completion_signatures_for.hpp>
2930
#include <beman/execution/detail/default_impls.hpp>
31+
#include <beman/execution/detail/env_of_t.hpp>
3032
#include <beman/execution/detail/get_env.hpp>
3133
#include <beman/execution/detail/impls_for.hpp>
3234
#include <beman/execution/detail/make_sender.hpp>
@@ -59,18 +61,21 @@ struct read_env_t {
5961
};
6062

6163
public:
62-
template <typename Sender, typename... Env>
64+
template <typename Sender, typename Env>
6365
static consteval auto get_completion_signatures() {
64-
return typename get_signatures<::std::remove_cvref_t<Sender>, Env...>::type{};
66+
return typename get_signatures<::std::remove_cvref_t<Sender>, Env>::type{};
6567
}
6668
struct impls_for : ::beman::execution::detail::default_impls {
6769
struct start_impl {
68-
auto operator()(auto query, auto& receiver) const noexcept -> void {
70+
template <typename Query, typename Receiver>
71+
auto operator()(Query query, Receiver& receiver) const noexcept -> void {
6972
try {
7073
auto env{::beman::execution::get_env(receiver)};
7174
::beman::execution::set_value(::std::move(receiver), query(env));
7275
} catch (...) {
73-
::beman::execution::set_error(::std::move(receiver), ::std::current_exception());
76+
if constexpr (!std::is_nothrow_invocable_v<Query, ::beman::execution::env_of_t<Receiver>>) {
77+
::beman::execution::set_error(::std::move(receiver), ::std::current_exception());
78+
}
7479
}
7580
}
7681
};

include/beman/execution/detail/sender.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ concept enable_sender =
4242
} // namespace beman::execution::detail
4343
namespace beman::execution {
4444
template <typename Sender>
45-
concept sender = ::beman::execution::detail::enable_sender<::std::remove_cvref_t<Sender>> &&
45+
inline constexpr bool enable_sender = ::beman::execution::detail::enable_sender<Sender>;
46+
47+
template <typename Sender>
48+
concept sender = ::beman::execution::enable_sender<::std::remove_cvref_t<Sender>> &&
4649
requires(const ::std::remove_cvref_t<Sender>& sndr) {
4750
{ ::beman::execution::get_env(sndr) } -> ::beman::execution::detail::queryable;
4851
} && ::std::move_constructible<::std::remove_cvref_t<Sender>> &&

include/beman/execution/detail/then.hpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import beman.execution.detail.completion_signatures;
2121
import beman.execution.detail.completion_signatures_for;
2222
import beman.execution.detail.completion_signatures_of_t;
2323
import beman.execution.detail.default_impls;
24+
import beman.execution.detail.dependent_sender;
25+
import beman.execution.detail.dependent_sender_error;
26+
import beman.execution.detail.env;
2427
import beman.execution.detail.get_domain_early;
2528
import beman.execution.detail.impls_for;
2629
import beman.execution.detail.make_sender;
@@ -41,6 +44,9 @@ import beman.execution.detail.transform_sender;
4144
#include <beman/execution/detail/completion_signatures_for.hpp>
4245
#include <beman/execution/detail/completion_signatures_of_t.hpp>
4346
#include <beman/execution/detail/default_impls.hpp>
47+
#include <beman/execution/detail/dependent_sender.hpp>
48+
#include <beman/execution/detail/dependent_sender_error.hpp>
49+
#include <beman/execution/detail/env.hpp>
4450
#include <beman/execution/detail/get_domain_early.hpp>
4551
#include <beman/execution/detail/impls_for.hpp>
4652
#include <beman/execution/detail/make_sender.hpp>
@@ -125,17 +131,19 @@ struct then_t : ::beman::execution::sender_adaptor_closure<then_t<Completion>> {
125131
private:
126132
template <typename, typename...>
127133
struct get_signatures;
128-
template <typename Comp, typename Fun, typename Child, typename... Env>
134+
template <typename Sender>
135+
struct get_signatures<Sender> : get_signatures<Sender, ::beman::execution::env<>> {};
136+
template <typename Comp, typename Fun, typename Child, typename Env>
129137
struct get_signatures<
130138
::beman::execution::detail::basic_sender<::beman::execution::detail::then_t<Comp>, Fun, Child>,
131-
Env...> {
139+
Env> {
132140
using type = ::beman::execution::detail::meta::unique<::beman::execution::detail::meta::combine<
133141
::beman::execution::detail::meta::transform<
134142
::beman::execution::detail::then_transform_t<Fun, Comp>::template transform,
135-
::beman::execution::completion_signatures_of_t<Child, Env...>>,
143+
::beman::execution::completion_signatures_of_t<Child, Env>>,
136144
::std::conditional_t<
137145
::beman::execution::detail::
138-
then_exception<Comp, Fun, ::beman::execution::completion_signatures_of_t<Child, Env...>>::value,
146+
then_exception<Comp, Fun, ::beman::execution::completion_signatures_of_t<Child, Env>>::value,
139147
::beman::execution::completion_signatures<::beman::execution::set_error_t(::std::exception_ptr)>,
140148
::beman::execution::completion_signatures<>>>>;
141149
};

0 commit comments

Comments
 (0)