Skip to content

Commit 7e4e3c6

Browse files
committed
Merge branch 'main' of https://github.com/nvidia/stdexec into mpsc-bug
2 parents 880029e + 1687898 commit 7e4e3c6

27 files changed

+2454
-237
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ callgrind.*
1616
a.out
1717
*.code-workspace
1818
/include/asioexec/asio_config.hpp
19+
.venv-codex

include/exec/fork_join.hpp

Lines changed: 40 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@
2323
namespace exec {
2424
struct PREDECESSOR_RESULTS_ARE_NOT_DECAY_COPYABLE { };
2525

26-
struct fork_join_t {
27-
template <class Sndr, class... Closures>
28-
struct _sndr_t;
29-
26+
struct fork_join_impl_t {
3027
struct _dematerialize_fn {
3128
struct _impl_fn {
3229
template <class Rcvr, class Tag, class... Args>
@@ -135,12 +132,13 @@ namespace exec {
135132
using _child_completions_t = STDEXEC::__completion_signatures_of_t<Sndr, _env_t>;
136133
using _domain_t = STDEXEC::__completion_domain_of_t<STDEXEC::set_value_t, Sndr, _env_t>;
137134
using _when_all_sndr_t =
138-
fork_join_t::_when_all_sndr_t<_child_completions_t, Closures, _domain_t>;
135+
fork_join_impl_t::_when_all_sndr_t<_child_completions_t, Closures, _domain_t>;
139136
using _child_opstate_t =
140137
STDEXEC::connect_result_t<Sndr, STDEXEC::__rcvr_ref_t<_opstate_t, _env_t>>;
141138
using _fork_opstate_t =
142139
STDEXEC::connect_result_t<_when_all_sndr_t, STDEXEC::__rcvr_ref_t<Rcvr>>;
143-
using _cache_sndr_t = fork_join_t::_cache_sndr_t<_variant_t<_child_completions_t>, _domain_t>;
140+
using _cache_sndr_t =
141+
fork_join_impl_t::_cache_sndr_t<_variant_t<_child_completions_t>, _domain_t>;
144142

145143
STDEXEC_ATTRIBUTE(host, device)
146144
constexpr explicit _opstate_t(Sndr&& sndr, Closures&& closures, Rcvr rcvr) noexcept
@@ -213,51 +211,45 @@ namespace exec {
213211
STDEXEC::__manual_lifetime<_child_opstate_t> _child_opstate_{};
214212
_fork_opstate_t _fork_opstate_;
215213
};
214+
};
216215

217-
template <class... Closures>
218-
struct _closure_t {
219-
using _closures_t = STDEXEC::__tuple<Closures...>;
220-
221-
template <class Sndr>
222-
STDEXEC_ATTRIBUTE(host, device)
223-
friend constexpr auto
224-
operator|(Sndr sndr, _closure_t self) noexcept -> _sndr_t<Sndr, Closures...> {
225-
return _sndr_t<Sndr, Closures...>{
226-
{}, static_cast<_closures_t&&>(self._closures_), static_cast<Sndr&&>(sndr)};
227-
}
228-
229-
_closures_t _closures_;
230-
};
231-
216+
struct fork_join_t {
232217
template <class Sndr, class... Closures>
233218
requires STDEXEC::sender<Sndr>
234219
STDEXEC_ATTRIBUTE(host, device)
235-
auto operator()(Sndr sndr, Closures... closures) const -> _sndr_t<Sndr, Closures...> {
236-
return {{}, {static_cast<Closures&&>(closures)...}, static_cast<Sndr&&>(sndr)};
220+
constexpr auto
221+
operator()(Sndr&& sndr, Closures&&... closures) const -> STDEXEC::__well_formed_sender auto {
222+
return STDEXEC::__make_sexpr<fork_join_t>(
223+
STDEXEC::__tuple{std::forward<Closures>(closures)...}, std::forward<Sndr>(sndr));
237224
}
238225

239226
template <class... Closures>
240227
requires((!STDEXEC::sender<Closures>) && ...)
241228
STDEXEC_ATTRIBUTE(host, device)
242-
auto operator()(Closures... closures) const -> _closure_t<Closures...> {
243-
return {{static_cast<Closures&&>(closures)...}};
229+
constexpr auto operator()(Closures&&... closures) const {
230+
return STDEXEC::__closure{*this, std::forward<Closures>(closures)...};
244231
}
245232
};
246233

247234
template <>
248-
struct fork_join_t::_env_t<STDEXEC::indeterminate_domain<>> { };
235+
struct fork_join_impl_t::_env_t<STDEXEC::indeterminate_domain<>> { };
249236

250-
template <class Sndr, class... Closures>
251-
struct fork_join_t::_sndr_t {
252-
using sender_concept = STDEXEC::sender_t;
253-
using _closures_t = STDEXEC::__tuple<Closures...>;
237+
inline constexpr fork_join_t fork_join{};
238+
239+
} // namespace exec
254240

241+
namespace exec::__fork_join {
242+
struct __impls : STDEXEC::__sexpr_defaults {
255243
template <class Self, class... Env>
256244
STDEXEC_ATTRIBUTE(host, device)
257245
static consteval auto get_completion_signatures() {
258246
using namespace STDEXEC;
259-
using _domain_t = STDEXEC::__completion_domain_of_t<set_value_t, Sndr, Env...>;
260-
using _child_t = __copy_cvref_t<Self, Sndr>;
247+
248+
using _closures_t = STDEXEC::__data_of<Self>;
249+
using _child_sndr_t = STDEXEC::__child_of<Self>;
250+
251+
using _domain_t = __completion_domain_of_t<set_value_t, _child_sndr_t, Env...>;
252+
using _child_t = __copy_cvref_t<Self, _child_sndr_t>;
261253
using _child_completions_t = __completion_signatures_of_t<_child_t, __fwd_env_t<Env>...>;
262254
using __decay_copyable_results_t = STDEXEC::__decay_copyable_results_t<_child_completions_t>;
263255

@@ -269,37 +261,26 @@ namespace exec {
269261
_IN_ALGORITHM_(exec::fork_join_t)
270262
>();
271263
} else {
272-
using _sndr_t = _when_all_sndr_t<_child_completions_t, _closures_t, _domain_t>;
264+
using _sndr_t =
265+
fork_join_impl_t::_when_all_sndr_t<_child_completions_t, _closures_t, _domain_t>;
273266
return __completion_signatures_of_t<_sndr_t, __fwd_env_t<Env>...>{};
274267
}
275268
}
276269

277-
template <class Rcvr>
278-
STDEXEC_ATTRIBUTE(host, device)
279-
constexpr auto connect(Rcvr rcvr) && -> _opstate_t<Sndr, _closures_t, Rcvr> {
280-
return _opstate_t<Sndr, _closures_t, Rcvr>{
281-
static_cast<Sndr&&>(sndr_),
282-
static_cast<_closures_t&&>(_closures_),
283-
static_cast<Rcvr&&>(rcvr)};
284-
}
285-
286-
template <class Rcvr>
287-
STDEXEC_ATTRIBUTE(host, device)
288-
constexpr auto connect(
289-
Rcvr rcvr) const & -> _opstate_t<Sndr const &, _closures_t const &, Rcvr> {
290-
return _opstate_t<Sndr const &, _closures_t const &, Rcvr>{
291-
sndr_, _closures_, static_cast<Rcvr&&>(rcvr)};
292-
}
293-
294-
STDEXEC_ATTRIBUTE(host, device)
295-
constexpr auto get_env() const noexcept -> STDEXEC::__fwd_env_t<STDEXEC::env_of_t<Sndr>> {
296-
return STDEXEC::__fwd_env(STDEXEC::get_env(sndr_));
297-
}
270+
static constexpr auto connect =
271+
[]<class _Receiver, class _Sender>(_Sender&& __sndr, _Receiver&& __rcvr) noexcept {
272+
using _closures_t = STDEXEC::__data_of<_Sender>;
273+
using _sndr_t = STDEXEC::__child_of<_Sender>;
298274

299-
STDEXEC_ATTRIBUTE(no_unique_address) fork_join_t _tag_;
300-
STDEXEC::__tuple<Closures...> _closures_;
301-
Sndr sndr_;
275+
return fork_join_impl_t::_opstate_t<_sndr_t, _closures_t, _Receiver>{
276+
STDEXEC::__get<2>(static_cast<_Sender&&>(__sndr)),
277+
STDEXEC::__get<1>(static_cast<_Sender&&>(__sndr)),
278+
static_cast<_Receiver&&>(__rcvr)};
279+
};
302280
};
281+
} // namespace exec::__fork_join
303282

304-
inline constexpr fork_join_t fork_join{};
305-
} // namespace exec
283+
namespace STDEXEC {
284+
template <>
285+
struct __sexpr_impl<exec::fork_join_t> : exec::__fork_join::__impls { };
286+
} // namespace STDEXEC

include/exec/sequence_senders.hpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -137,16 +137,16 @@ namespace exec {
137137

138138
template <receiver _Receiver, sender _Item>
139139
requires __has_set_next_member<_Receiver, _Item>
140-
|| tag_invocable<set_next_t, _Receiver&, _Item>
140+
|| __tag_invocable<set_next_t, _Receiver&, _Item>
141141
[[deprecated("the use of tag_invoke for set_next is deprecated")]]
142142
auto operator()(_Receiver& __rcvr, _Item&& __item) const
143-
noexcept(nothrow_tag_invocable<set_next_t, _Receiver&, _Item>)
144-
-> tag_invoke_result_t<set_next_t, _Receiver&, _Item> {
143+
noexcept(__nothrow_tag_invocable<set_next_t, _Receiver&, _Item>)
144+
-> __tag_invoke_result_t<set_next_t, _Receiver&, _Item> {
145145
static_assert(
146-
next_sender<tag_invoke_result_t<set_next_t, _Receiver&, _Item>>,
146+
next_sender<__tag_invoke_result_t<set_next_t, _Receiver&, _Item>>,
147147
"The sender returned from set_next is required to complete with set_value_t() or "
148148
"set_stopped_t()");
149-
return tag_invoke(*this, __rcvr, static_cast<_Item&&>(__item));
149+
return __tag_invoke(*this, __rcvr, static_cast<_Item&&>(__item));
150150
}
151151
};
152152
} // namespace __sequence_sndr
@@ -292,7 +292,7 @@ namespace exec {
292292
__minvocable_q<__consteval_static_member_result_t, _Sequence, _Env...>;
293293

294294
template <class _Sequence, class... _Env>
295-
concept __with_tag_invoke = tag_invocable<get_item_types_t, _Sequence, _Env...>;
295+
concept __with_tag_invoke = __tag_invocable<get_item_types_t, _Sequence, _Env...>;
296296

297297
template <class _Sequence, class... _Env>
298298
[[nodiscard]]
@@ -314,7 +314,7 @@ namespace exec {
314314
} else if constexpr (__with_consteval_static_member<_Sequence>) {
315315
return STDEXEC_REMOVE_REFERENCE(_Sequence)::template get_item_types<_Sequence>();
316316
} else if constexpr (__with_tag_invoke<_Sequence, _Env...>) {
317-
using __result_t = tag_invoke_result_t<get_item_types_t, _Sequence, _Env...>;
317+
using __result_t = __tag_invoke_result_t<get_item_types_t, _Sequence, _Env...>;
318318
return __result_t();
319319
} else if constexpr (
320320
sender_in<_Sequence, _Env...> && !enable_sequence_sender<STDEXEC::__decay_t<_Sequence>>) {
@@ -659,7 +659,7 @@ namespace exec {
659659
__minvocable_q<__subscribe_static_member_result_t, _Sequence, _Receiver>;
660660

661661
template <class _Sequence, class _Receiver>
662-
concept __subscribable_with_tag_invoke = tag_invocable<subscribe_t, _Sequence, _Receiver>;
662+
concept __subscribable_with_tag_invoke = __tag_invocable<subscribe_t, _Sequence, _Receiver>;
663663

664664
struct subscribe_t {
665665
private:
@@ -791,30 +791,30 @@ namespace exec {
791791
auto _DeclFn = __get_declfn<_Sequence, _Receiver>()
792792
>
793793
requires STDEXEC::__callable<decltype(_DeclFn)>
794-
|| STDEXEC::tag_invocable<
794+
|| STDEXEC::__tag_invocable<
795795
subscribe_t,
796796
__transform_sender_result_t<_Sequence, _Receiver>,
797797
_Receiver
798798
>
799799
[[deprecated("the use of tag_invoke for subscribe is deprecated")]]
800800
auto operator()(_Sequence&& __sequence, _Receiver __rcvr) const noexcept(
801801
__nothrow_callable<transform_sender_t, _Sequence, env_of_t<_Receiver>>
802-
&& STDEXEC::nothrow_tag_invocable<
802+
&& STDEXEC::__nothrow_tag_invocable<
803803
subscribe_t,
804804
__transform_sender_result_t<_Sequence, _Receiver>,
805805
_Receiver
806806
>)
807-
-> STDEXEC::tag_invoke_result_t<
807+
-> STDEXEC::__tag_invoke_result_t<
808808
subscribe_t,
809809
__transform_sender_result_t<_Sequence, _Receiver>,
810810
_Receiver
811811
> {
812812
using __tfx_seq_t = __transform_sender_result_t<_Sequence, _Receiver>;
813-
using __result_t = tag_invoke_result_t<subscribe_t, __tfx_seq_t, _Receiver>;
813+
using __result_t = __tag_invoke_result_t<subscribe_t, __tfx_seq_t, _Receiver>;
814814
__check_operation_state<__result_t>();
815815
auto&& __env = STDEXEC::get_env(__rcvr);
816816
auto&& __tfx_seq = STDEXEC::transform_sender(static_cast<_Sequence&&>(__sequence), __env);
817-
return STDEXEC::tag_invoke(
817+
return STDEXEC::__tag_invoke(
818818
subscribe_t{}, static_cast<__tfx_seq_t&&>(__tfx_seq), static_cast<_Receiver&&>(__rcvr));
819819
}
820820

include/exec/timed_scheduler.hpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ namespace exec {
4949
}
5050

5151
template <class _Scheduler>
52-
requires __has_now<_Scheduler> || tag_invocable<now_t, const _Scheduler&>
52+
requires __has_now<_Scheduler> || __tag_invocable<now_t, const _Scheduler&>
5353
[[deprecated("the use of tag_invoke for exec::now() is deprecated")]]
5454
STDEXEC_ATTRIBUTE(always_inline) //
5555
auto operator()(const _Scheduler& __sched) const
56-
noexcept(nothrow_tag_invocable<now_t, const _Scheduler&>)
57-
-> __decay_t<tag_invoke_result_t<now_t, const _Scheduler&>> {
58-
static_assert(time_point<__decay_t<tag_invoke_result_t<now_t, const _Scheduler&>>>);
59-
return tag_invoke(now_t{}, __sched);
56+
noexcept(__nothrow_tag_invocable<now_t, const _Scheduler&>)
57+
-> __decay_t<__tag_invoke_result_t<now_t, const _Scheduler&>> {
58+
static_assert(time_point<__decay_t<__tag_invoke_result_t<now_t, const _Scheduler&>>>);
59+
return __tag_invoke(now_t{}, __sched);
6060
}
6161
};
6262
} // namespace __now
@@ -116,18 +116,18 @@ namespace exec {
116116

117117
template <class _Scheduler>
118118
requires __has_schedule_after_member<_Scheduler>
119-
|| tag_invocable<schedule_after_t, _Scheduler, const duration_of_t<_Scheduler>&>
119+
|| __tag_invocable<schedule_after_t, _Scheduler, const duration_of_t<_Scheduler>&>
120120
[[deprecated("the use of tag_invoke for exec::schedule_after is deprecated")]]
121121
STDEXEC_ATTRIBUTE(always_inline) //
122122
auto operator()(_Scheduler&& __sched, const duration_of_t<_Scheduler>& __duration) const
123123
noexcept(
124-
nothrow_tag_invocable<schedule_after_t, _Scheduler, const duration_of_t<_Scheduler>&>)
125-
-> tag_invoke_result_t<schedule_after_t, _Scheduler, const duration_of_t<_Scheduler>&> {
124+
__nothrow_tag_invocable<schedule_after_t, _Scheduler, const duration_of_t<_Scheduler>&>)
125+
-> __tag_invoke_result_t<schedule_after_t, _Scheduler, const duration_of_t<_Scheduler>&> {
126126
static_assert(
127127
sender<
128-
tag_invoke_result_t<schedule_after_t, _Scheduler, const duration_of_t<_Scheduler>&>
128+
__tag_invoke_result_t<schedule_after_t, _Scheduler, const duration_of_t<_Scheduler>&>
129129
>);
130-
return tag_invoke(schedule_after, static_cast<_Scheduler&&>(__sched), __duration);
130+
return __tag_invoke(schedule_after, static_cast<_Scheduler&&>(__sched), __duration);
131131
}
132132
};
133133

@@ -189,18 +189,18 @@ namespace exec {
189189

190190
template <class _Scheduler>
191191
requires __has_schedule_at_member<_Scheduler>
192-
|| tag_invocable<schedule_at_t, _Scheduler, const time_point_of_t<_Scheduler>&>
192+
|| __tag_invocable<schedule_at_t, _Scheduler, const time_point_of_t<_Scheduler>&>
193193
[[deprecated("the use of tag_invoke for exec::schedule_at is deprecated")]]
194194
STDEXEC_ATTRIBUTE(always_inline) //
195195
auto operator()(_Scheduler&& __sched, const time_point_of_t<_Scheduler>& __time_point) const
196196
noexcept(
197-
nothrow_tag_invocable<schedule_at_t, _Scheduler, const time_point_of_t<_Scheduler>&>)
198-
-> tag_invoke_result_t<schedule_at_t, _Scheduler, const time_point_of_t<_Scheduler>&> {
197+
__nothrow_tag_invocable<schedule_at_t, _Scheduler, const time_point_of_t<_Scheduler>&>)
198+
-> __tag_invoke_result_t<schedule_at_t, _Scheduler, const time_point_of_t<_Scheduler>&> {
199199
static_assert(
200200
sender<
201-
tag_invoke_result_t<schedule_at_t, _Scheduler, const time_point_of_t<_Scheduler>&>
201+
__tag_invoke_result_t<schedule_at_t, _Scheduler, const time_point_of_t<_Scheduler>&>
202202
>);
203-
return tag_invoke(schedule_at, static_cast<_Scheduler&&>(__sched), __time_point);
203+
return __tag_invoke(schedule_at, static_cast<_Scheduler&&>(__sched), __time_point);
204204
}
205205
};
206206

0 commit comments

Comments
 (0)