Skip to content

Commit dcb3768

Browse files
committed
tweak __sexpr to require fewer transform_sender gyrations
1 parent bc97adf commit dcb3768

37 files changed

Lines changed: 1047 additions & 1039 deletions

include/exec/completion_signatures.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ namespace exec {
6161
//! @tparam DeducedSigs Completion signature types to be deduced from the function arguments.
6262
//! @param unnamed Pointer arguments (unused) used for type deduction of DeducedSigs.
6363
//!
64-
//! @return An instance of `detail::make_completion_signatures_t` containing the combined
64+
//! @return An instance of `STDEXEC::completion_signatures` containing the combined
6565
//! signatures.
6666
//!
6767
//! @note This is a `consteval` function, meaning it is only callable in constant evaluation

include/exec/fork_join.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ namespace exec {
131131
template <class Sndr, class Closures, class Rcvr>
132132
struct _opstate_t {
133133
using operation_state_concept = STDEXEC::operation_state_t;
134-
using _env_t = STDEXEC::__call_result_t<STDEXEC::__env::__fwd_fn, STDEXEC::env_of_t<Rcvr>>;
134+
using _env_t = STDEXEC::__fwd_env_t<STDEXEC::env_of_t<Rcvr>>;
135135
using _child_completions_t = STDEXEC::__completion_signatures_of_t<Sndr, _env_t>;
136136
using _domain_t = STDEXEC::__completion_domain_of_t<STDEXEC::set_value_t, Sndr, _env_t>;
137137
using _when_all_sndr_t =
@@ -204,7 +204,7 @@ namespace exec {
204204
}
205205

206206
STDEXEC_ATTRIBUTE(nodiscard, host, device)
207-
constexpr auto get_env() const noexcept -> STDEXEC::__fwd_env_t<STDEXEC::env_of_t<Rcvr>> {
207+
constexpr auto get_env() const noexcept -> _env_t {
208208
return STDEXEC::__fwd_env(STDEXEC::get_env(_rcvr_));
209209
}
210210

include/exec/repeat_n.hpp

Lines changed: 42 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ namespace exec {
3535
using namespace STDEXEC;
3636

3737
template <class _Receiver>
38-
struct __repeat_n_state_base {
39-
constexpr explicit __repeat_n_state_base(_Receiver &&__rcvr, std::size_t __count) noexcept
38+
struct __opstate_base : __immovable {
39+
constexpr explicit __opstate_base(_Receiver &&__rcvr, std::size_t __count) noexcept
4040
: __rcvr_{static_cast<_Receiver &&>(__rcvr)}
4141
, __count_{__count} {
4242
}
@@ -49,9 +49,8 @@ namespace exec {
4949
trampoline_scheduler __sched_;
5050
};
5151

52-
template <class _SenderId, class _ReceiverId>
52+
template <class _ReceiverId>
5353
struct __receiver {
54-
using _Sender = STDEXEC::__t<_SenderId>;
5554
using _Receiver = STDEXEC::__t<_ReceiverId>;
5655

5756
struct __t {
@@ -86,54 +85,43 @@ namespace exec {
8685
return STDEXEC::get_env(__state_->__rcvr_);
8786
}
8887

89-
__repeat_n_state_base<_Receiver> *__state_;
88+
__opstate_base<_Receiver> *__state_;
9089
};
9190
};
9291

93-
template <class _Child>
94-
struct __child_count_pair {
95-
_Child __child_;
96-
std::size_t __count_;
97-
};
98-
99-
template <class _Child>
100-
STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE
101-
__child_count_pair(_Child, std::size_t) -> __child_count_pair<_Child>;
102-
103-
template <class _Sender, class _Receiver>
104-
struct __repeat_n_state : __repeat_n_state_base<_Receiver> {
105-
using __child_count_pair_t = __decay_t<__data_of<_Sender>>;
106-
using __child_t = decltype(__child_count_pair_t::__child_);
107-
using __receiver_t = STDEXEC::__t<__receiver<__id<_Sender>, __id<_Receiver>>>;
108-
using __child_on_sched_sender_t =
109-
__result_of<exec::sequence, schedule_result_t<trampoline_scheduler>, __child_t &>;
110-
using __child_op_t = STDEXEC::connect_result_t<__child_on_sched_sender_t, __receiver_t>;
111-
112-
constexpr explicit __repeat_n_state(_Sender &&__sndr, _Receiver &&__rcvr)
113-
: __repeat_n_state_base<_Receiver>{
114-
static_cast<_Receiver &&>(__rcvr),
115-
STDEXEC::__get<1>(static_cast<_Sender &&>(__sndr)).__count_}
116-
, __child_(STDEXEC::__get<1>(static_cast<_Sender &&>(__sndr)).__child_) {
92+
template <class _Child, class _Receiver>
93+
struct __opstate : __opstate_base<_Receiver> {
94+
using __receiver_t = STDEXEC::__t<__receiver<__id<_Receiver>>>;
95+
using __bouncy_sndr_t =
96+
__result_of<exec::sequence, schedule_result_t<trampoline_scheduler>, _Child &>;
97+
using __child_op_t = STDEXEC::connect_result_t<__bouncy_sndr_t, __receiver_t>;
98+
static constexpr bool __nothrow_connect =
99+
STDEXEC::__nothrow_connectable<__bouncy_sndr_t, __receiver_t>;
100+
101+
constexpr explicit __opstate(std::size_t __count, _Child __child, _Receiver __rcvr)
102+
noexcept(__nothrow_connect)
103+
: __opstate_base<_Receiver>{static_cast<_Receiver &&>(__rcvr), __count}
104+
, __child_(std::move(__child)) {
117105
if (this->__count_ != 0) {
118106
__connect();
119107
}
120108
}
121109

122-
constexpr auto __connect() -> __child_op_t & {
123-
return __child_op_.__emplace_from(
124-
STDEXEC::connect,
125-
exec::sequence(STDEXEC::schedule(this->__sched_), __child_),
126-
__receiver_t{this});
127-
}
128-
129-
constexpr void __start() noexcept {
110+
constexpr void start() noexcept {
130111
if (this->__count_ == 0) {
131112
STDEXEC::set_value(static_cast<_Receiver &&>(this->__rcvr_));
132113
} else {
133114
STDEXEC::start(*__child_op_);
134115
}
135116
}
136117

118+
constexpr auto __connect() noexcept(__nothrow_connect) -> __child_op_t & {
119+
return __child_op_.__emplace_from(
120+
STDEXEC::connect,
121+
exec::sequence(STDEXEC::schedule(this->__sched_), __child_),
122+
__receiver_t{this});
123+
}
124+
137125
constexpr void __cleanup() noexcept final {
138126
__child_op_.reset();
139127
}
@@ -153,18 +141,14 @@ namespace exec {
153141
}
154142
}
155143

156-
__child_t __child_;
144+
_Child __child_;
157145
STDEXEC::__optional<__child_op_t> __child_op_;
158146
};
159147

160-
template <class _Sender, class _Receiver>
161-
STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE
162-
__repeat_n_state(_Sender &&, _Receiver) -> __repeat_n_state<_Sender, _Receiver>;
163-
164148
struct repeat_n_t;
165149
struct _REPEAT_N_EXPECTS_A_SENDER_OF_VOID_;
166150

167-
template <class _Sender, class... _Args>
151+
template <class _Child, class... _Args>
168152
using __values_t =
169153
// There's something funny going on with __if_c here. Use std::conditional_t instead. :-(
170154
std::conditional_t<
@@ -173,43 +157,41 @@ namespace exec {
173157
__mexception<
174158
_REPEAT_N_EXPECTS_A_SENDER_OF_VOID_,
175159
_WHERE_(_IN_ALGORITHM_, repeat_n_t),
176-
_WITH_PRETTY_SENDER_<_Sender>
160+
_WITH_PRETTY_SENDER_<_Child>
177161
>
178162
>;
179163

180164
template <class _Error>
181165
using __error_t = completion_signatures<set_error_t(__decay_t<_Error>)>;
182166

183-
template <class _Pair, class... _Env>
167+
template <class _Child, class... _Env>
184168
using __completions_t = STDEXEC::transform_completion_signatures<
185-
__completion_signatures_of_t<decltype(__decay_t<_Pair>::__child_) &, _Env...>,
169+
__completion_signatures_of_t<_Child &, _Env...>,
186170
STDEXEC::transform_completion_signatures<
187171
__completion_signatures_of_t<STDEXEC::schedule_result_t<exec::trampoline_scheduler>, _Env...>,
188172
__eptr_completion,
189173
__cmplsigs::__default_set_value,
190174
__error_t
191175
>,
192-
__mbind_front_q<__values_t, decltype(__decay_t<_Pair>::__child_)>::template __f,
176+
__mbind_front_q<__values_t, _Child>::template __f,
193177
__error_t
194178
>;
195179

196-
struct __repeat_n_tag { };
197-
198-
struct __repeat_n_impl : __sexpr_defaults {
180+
struct __impls : __sexpr_defaults {
199181
template <class _Sender, class... _Env>
200182
static consteval auto get_completion_signatures() {
201183
// TODO: port this to use constant evaluation
202-
return __completions_t<__data_of<_Sender>, _Env...>{};
184+
return __completions_t<__child_of<_Sender>, _Env...>{};
203185
}
204186

205-
static constexpr auto get_state = []<class _Sender, class _Receiver>(
206-
_Sender &&__sndr,
207-
_Receiver &&__rcvr) {
208-
return __repeat_n_state{static_cast<_Sender &&>(__sndr), static_cast<_Receiver &&>(__rcvr)};
209-
};
210-
211-
static constexpr auto start = [](auto &__state) noexcept -> void {
212-
__state.__start();
187+
static constexpr auto connect = //
188+
[]<class _Receiver, class _Sender>(_Sender &&__sndr, _Receiver &&__rcvr) noexcept(
189+
noexcept(__opstate(0, STDEXEC::__get<2>(__declval<_Sender>()), __declval<_Receiver>()))) {
190+
const std::size_t __count = STDEXEC::__get<1>(__sndr);
191+
return __opstate(
192+
__count,
193+
STDEXEC::__get<2>(static_cast<_Sender &&>(__sndr)),
194+
static_cast<_Receiver &&>(__rcvr));
213195
};
214196
};
215197

@@ -223,14 +205,6 @@ namespace exec {
223205
constexpr auto operator()(std::size_t __count) const noexcept {
224206
return __closure(*this, __count);
225207
}
226-
227-
template <class _Sender>
228-
static auto transform_sender(set_value_t, _Sender &&__sndr, __ignore)
229-
noexcept(__nothrow_decay_copyable<_Sender>) {
230-
auto &[__tag, __count, __child] = __sndr;
231-
return __make_sexpr<__repeat_n_tag>(
232-
__child_count_pair{STDEXEC::__forward_like<_Sender>(__child), __count});
233-
}
234208
};
235209
} // namespace __repeat_n
236210

@@ -240,17 +214,7 @@ namespace exec {
240214

241215
namespace STDEXEC {
242216
template <>
243-
struct __sexpr_impl<exec::__repeat_n::__repeat_n_tag> : exec::__repeat_n::__repeat_n_impl { };
244-
245-
template <>
246-
struct __sexpr_impl<exec::repeat_n_t> : __sexpr_defaults {
247-
template <class _Sender, class... _Env>
248-
static consteval auto get_completion_signatures() {
249-
using __sndr_t =
250-
__detail::__transform_sender_result_t<exec::repeat_n_t, set_value_t, _Sender, env<>>;
251-
return STDEXEC::get_completion_signatures<__sndr_t, _Env...>();
252-
};
253-
};
217+
struct __sexpr_impl<exec::repeat_n_t> : exec::__repeat_n::__impls { };
254218
} // namespace STDEXEC
255219

256220
STDEXEC_PRAGMA_POP()

0 commit comments

Comments
 (0)