Skip to content

Commit ddb76f1

Browse files
authored
Merge branch 'main' into p3892
2 parents 5146387 + 6d1644b commit ddb76f1

File tree

9 files changed

+1058
-228
lines changed

9 files changed

+1058
-228
lines changed

.github/workflows/ci.cpu.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ jobs:
2323
- { name: "CPU (clang 16, Release)", build: "Release", tag: llvm16-cuda12.9, cxxflags: "-stdlib=libc++" }
2424
- { name: "CPU (gcc 11, Debug)", build: "Debug", tag: gcc11-cuda12.9, cxxflags: "", }
2525
- { name: "CPU (gcc 11, Release)", build: "Release", tag: gcc11-cuda12.9, cxxflags: "", }
26-
- { name: "CPU (gcc 11, Release, TSAN)", build: "Release", tag: gcc11-cuda12.9, cxxflags: "-fsanitize=thread" }
2726
- { name: "CPU (gcc 11, Release, ASAN)", build: "Release", tag: gcc11-cuda12.9, cxxflags: "-fsanitize=address" }
27+
- { name: "CPU (gcc 12, Release, TSAN)", build: "Release", tag: gcc12-cuda12.9, cxxflags: "-fsanitize=thread" }
2828
container:
2929
options: -u root
3030
image: rapidsai/devcontainers:25.10-cpp-${{ matrix.tag }}

include/exec/__detail/__basic_sequence.hpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,35 +71,35 @@ namespace exec {
7171
return {};
7272
}
7373

74-
template <stdexec::__decays_to<__seqexpr> _Self, class _Env>
75-
STDEXEC_MEMFN_DECL(auto get_item_types)(this _Self&& __self, _Env&& __env)
74+
template <stdexec::__decays_to<__seqexpr> _Self, class... _Env>
75+
static auto get_item_types(_Self&& __self, _Env&&... __env)
7676
-> decltype(__self.__tag()
77-
.get_item_types(static_cast<_Self&&>(__self), static_cast<_Env&&>(__env))) {
77+
.get_item_types(static_cast<_Self&&>(__self), static_cast<_Env&&>(__env)...)) {
7878
return {};
7979
}
8080

8181
template <stdexec::__decays_to<__seqexpr> _Self, stdexec::receiver _Receiver>
82-
STDEXEC_MEMFN_DECL(auto subscribe)(this _Self&& __self, _Receiver&& __rcvr) noexcept(noexcept(
82+
static auto subscribe(_Self&& __self, _Receiver&& __rcvr) noexcept(noexcept(
8383
__self.__tag().subscribe(static_cast<_Self&&>(__self), static_cast<_Receiver&&>(__rcvr))))
8484
-> decltype(__self.__tag()
8585
.subscribe(static_cast<_Self&&>(__self), static_cast<_Receiver&&>(__rcvr))) {
8686
return __tag_t::subscribe(static_cast<_Self&&>(__self), static_cast<_Receiver&&>(__rcvr));
8787
}
8888

89-
template <class _Sender, class _ApplyFn>
90-
static auto
91-
apply(_Sender&& __sndr, _ApplyFn&& __fun) noexcept(stdexec::__nothrow_callable<
92-
stdexec::__detail::__impl_of<_Sender>,
93-
stdexec::__copy_cvref_fn<_Sender>,
94-
_ApplyFn
89+
template <class _Sequence, class _ApplyFn>
90+
static auto apply(_Sequence&& __sequence, _ApplyFn&& __fun)
91+
noexcept(stdexec::__nothrow_callable<
92+
stdexec::__detail::__impl_of<_Sequence>,
93+
stdexec::__copy_cvref_fn<_Sequence>,
94+
_ApplyFn
9595
>)
9696
-> stdexec::__call_result_t<
97-
stdexec::__detail::__impl_of<_Sender>,
98-
stdexec::__copy_cvref_fn<_Sender>,
97+
stdexec::__detail::__impl_of<_Sequence>,
98+
stdexec::__copy_cvref_fn<_Sequence>,
9999
_ApplyFn
100100
> {
101-
return static_cast<_Sender&&>(__sndr)
102-
.__impl_(stdexec::__copy_cvref_fn<_Sender>(), static_cast<_ApplyFn&&>(__fun));
101+
return static_cast<_Sequence&&>(__sequence)
102+
.__impl_(stdexec::__copy_cvref_fn<_Sequence>(), static_cast<_ApplyFn&&>(__fun));
103103
}
104104
};
105105

include/exec/sequence/ignore_all_values.hpp

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,6 @@ namespace exec {
276276
using __completion_sigs = __sequence_completion_signatures_of_t<_Child, _Env>;
277277

278278
template <class _Child>
279-
requires receiver_of<_Receiver, __completion_sigs<_Child>>
280-
&& sequence_sender_to<_Child, __receiver_t<_Child>>
281279
auto operator()(__ignore, __ignore, _Child&& __child)
282280
noexcept(__nothrow_constructible_from<__operation_t<_Child>, _Child, _Receiver>)
283281
-> __operation_t<_Child> {
@@ -287,7 +285,7 @@ namespace exec {
287285

288286
struct ignore_all_values_t {
289287
template <sender _Sender>
290-
auto operator()(_Sender&& __sndr) const {
288+
auto operator()(_Sender&& __sndr) const -> __well_formed_sender auto {
291289
auto __domain = __get_early_domain(static_cast<_Sender&&>(__sndr));
292290
return transform_sender(
293291
__domain, __make_sexpr<ignore_all_values_t>(__(), static_cast<_Sender&&>(__sndr)));
@@ -319,13 +317,7 @@ namespace exec {
319317
static constexpr auto connect =
320318
[]<class _Sender, receiver _Receiver>(_Sender&& __sndr, _Receiver __rcvr) noexcept(
321319
__nothrow_callable<__sexpr_apply_t, _Sender, __connect_fn<_Receiver>>)
322-
-> __call_result_t<__sexpr_apply_t, _Sender, __connect_fn<_Receiver>>
323-
requires receiver_of<_Receiver, __completion_sigs<__child_of<_Sender>, env_of_t<_Receiver>>>
324-
&& sequence_sender_to<
325-
__child_of<_Sender>,
326-
__receiver_t<__child_of<_Sender>, _Receiver>
327-
>
328-
{
320+
-> __call_result_t<__sexpr_apply_t, _Sender, __connect_fn<_Receiver>> {
329321
static_assert(sender_expr_for<_Sender, ignore_all_values_t>);
330322
return __sexpr_apply(static_cast<_Sender&&>(__sndr), __connect_fn<_Receiver>{__rcvr});
331323
};
@@ -340,4 +332,4 @@ namespace stdexec {
340332
template <>
341333
struct __sexpr_impl<exec::ignore_all_values_t>
342334
: exec::__ignore_all_values::__ignore_all_values_impl { };
343-
} // namespace stdexec
335+
} // namespace stdexec

include/exec/sequence/iterate.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ namespace exec {
167167
struct iterate_t {
168168
template <std::ranges::forward_range _Range>
169169
requires __decay_copyable<_Range>
170-
auto operator()(_Range&& __range) const {
170+
auto operator()(_Range&& __range) const -> __well_formed_sequence_sender auto {
171171
return make_sequence_expr<iterate_t>(__decay_t<_Range>{static_cast<_Range&&>(__range)});
172172
}
173173

@@ -219,4 +219,4 @@ namespace exec {
219219
inline constexpr iterate_t iterate;
220220
} // namespace exec
221221

222-
#endif // STDEXEC_HAS_STD_RANGES()
222+
#endif // STDEXEC_HAS_STD_RANGES()

include/exec/sequence/merge.hpp

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/*
2+
* Copyright (c) 2023 Maikel Nadolski
3+
* Copyright (c) 2023 NVIDIA Corporation
4+
*
5+
* Licensed under the Apache License Version 2.0 with LLVM Exceptions
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* https://llvm.org/LICENSE.txt
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
#pragma once
18+
19+
#include "../../stdexec/concepts.hpp"
20+
#include "../../stdexec/execution.hpp"
21+
#include "../sequence_senders.hpp"
22+
23+
#include "../__detail/__basic_sequence.hpp"
24+
#include "./transform_each.hpp"
25+
#include "./ignore_all_values.hpp"
26+
#include "stdexec/__detail/__execution_fwd.hpp"
27+
#include "stdexec/__detail/__meta.hpp"
28+
#include "stdexec/__detail/__senders_core.hpp"
29+
#include "stdexec/__detail/__transform_completion_signatures.hpp"
30+
31+
namespace exec {
32+
namespace __merge {
33+
using namespace stdexec;
34+
35+
template <class _Receiver>
36+
struct __operation_base {
37+
_Receiver __receiver_;
38+
};
39+
40+
template <class _ReceiverId>
41+
struct __result_receiver {
42+
using _Receiver = stdexec::__t<_ReceiverId>;
43+
44+
struct __t {
45+
using receiver_concept = stdexec::receiver_t;
46+
using __id = __result_receiver;
47+
48+
__operation_base<_Receiver>* __op_;
49+
50+
void set_value() noexcept {
51+
stdexec::set_value(static_cast<_Receiver&&>(__op_->__receiver_));
52+
}
53+
54+
template <class _Error>
55+
void set_error(_Error&& __error) noexcept {
56+
stdexec::set_error(
57+
static_cast<_Receiver&&>(__op_->__receiver_), static_cast<_Error&&>(__error));
58+
}
59+
60+
void set_stopped() noexcept {
61+
stdexec::set_stopped(static_cast<_Receiver&&>(__op_->__receiver_));
62+
}
63+
64+
auto get_env() const noexcept -> env_of_t<_Receiver> {
65+
return stdexec::get_env(__op_->__receiver_);
66+
}
67+
};
68+
};
69+
70+
template <class _ReceiverId>
71+
struct __merge_each_fn {
72+
using _Receiver = stdexec::__t<_ReceiverId>;
73+
74+
template <stdexec::sender _Item>
75+
auto operator()(_Item&& __item, __operation_base<_Receiver>* __op) const
76+
noexcept(__nothrow_callable<set_next_t, _Receiver&, _Item>)
77+
-> next_sender_of_t<_Receiver, _Item> {
78+
return exec::set_next(__op->__receiver_, static_cast<_Item&&>(__item));
79+
}
80+
};
81+
82+
struct __combine {
83+
template <class _ReceiverId>
84+
using merge_each_fn_t =
85+
__binder_back<__merge_each_fn<_ReceiverId>, __operation_base<__t<_ReceiverId>>*>;
86+
87+
template <class _Sequence, class _ReceiverId>
88+
using transform_sender_t =
89+
__call_result_t<exec::transform_each_t, _Sequence, merge_each_fn_t<_ReceiverId>>;
90+
template <class _Sequence, class _ReceiverId>
91+
using ignored_sender_t =
92+
__call_result_t<exec::ignore_all_values_t, transform_sender_t<_Sequence, _ReceiverId>>;
93+
94+
template <class _ReceiverId, class... _Sequences>
95+
using result_sender_t =
96+
__call_result_t<when_all_t, ignored_sender_t<_Sequences, _ReceiverId>...>;
97+
};
98+
99+
template <class _ReceiverId, class... _Sequences>
100+
struct __operation {
101+
using _Receiver = stdexec::__t<_ReceiverId>;
102+
103+
using merge_each_fn_t = typename __combine::merge_each_fn_t<_ReceiverId>;
104+
105+
template <class _ReceiverIdDependent>
106+
using result_sender_t =
107+
typename __combine::result_sender_t<_ReceiverIdDependent, _Sequences...>;
108+
109+
struct __t : __operation_base<_Receiver> {
110+
using __id = __operation;
111+
112+
connect_result_t<result_sender_t<_ReceiverId>, stdexec::__t<__result_receiver<_ReceiverId>>>
113+
__op_result_;
114+
115+
__t(_Receiver __rcvr, _Sequences... __sequences)
116+
: __operation_base<_Receiver>{static_cast<_Receiver&&>(__rcvr)}
117+
, __op_result_{stdexec::connect(
118+
stdexec::when_all(
119+
exec::ignore_all_values(
120+
exec::transform_each(
121+
static_cast<_Sequences&&>(__sequences),
122+
merge_each_fn_t{{this}, {}, {}}))...),
123+
stdexec::__t<__result_receiver<_ReceiverId>>{this})} {
124+
}
125+
126+
void start() & noexcept {
127+
stdexec::start(__op_result_);
128+
}
129+
};
130+
};
131+
132+
template <class _Receiver>
133+
struct __subscribe_fn {
134+
_Receiver& __rcvr_;
135+
136+
template <class... _Sequences>
137+
auto operator()(__ignore, __ignore, _Sequences... __sequences) noexcept(
138+
(__nothrow_decay_copyable<_Sequences> && ...) && __nothrow_move_constructible<_Receiver>)
139+
-> __t<__operation<__id<_Receiver>, _Sequences...>> {
140+
return {static_cast<_Receiver&&>(__rcvr_), static_cast<_Sequences&&>(__sequences)...};
141+
}
142+
};
143+
144+
struct merge_t {
145+
template <class... _Sequences>
146+
auto operator()(_Sequences&&... __sequences) const
147+
noexcept((__nothrow_decay_copyable<_Sequences> && ...)) -> __well_formed_sequence_sender
148+
auto {
149+
auto __domain = __common_domain_t<_Sequences...>();
150+
return transform_sender(
151+
__domain, make_sequence_expr<merge_t>(__(), static_cast<_Sequences&&>(__sequences)...));
152+
}
153+
154+
template <class _Error>
155+
using __set_error_t = completion_signatures<set_error_t(__decay_t<_Error>)>;
156+
157+
struct _INVALID_ARGUMENTS_TO_MERGE_ { };
158+
159+
template <class _Self, class _Env>
160+
using __error_t = __mexception<
161+
_INVALID_ARGUMENTS_TO_MERGE_,
162+
__children_of<_Self, __q<_WITH_SEQUENCES_>>,
163+
_WITH_ENVIRONMENT_<_Env>
164+
>;
165+
166+
template <class... _Env>
167+
struct __completions_fn_t {
168+
169+
template <class... _Sequences>
170+
using __f = __meval<
171+
__concat_completion_signatures,
172+
completion_signatures<set_stopped_t()>,
173+
__sequence_completion_signatures_of_t<_Sequences, _Env...>...
174+
>;
175+
};
176+
177+
template <class _Self, class... _Env>
178+
using __completions_t = __children_of<_Self, __completions_fn_t<_Env...>>;
179+
180+
template <sender_expr_for<merge_t> _Self, class... _Env>
181+
static auto get_completion_signatures(_Self&&, _Env&&...) noexcept {
182+
return __minvoke<__mtry_catch<__q<__completions_t>, __q<__error_t>>, _Self, _Env...>();
183+
}
184+
185+
template <class... _Env>
186+
struct __items_fn_t {
187+
188+
template <class... _Sequences>
189+
using __f = stdexec::__mapply<
190+
stdexec::__munique<stdexec::__q<exec::item_types>>,
191+
stdexec::__minvoke<
192+
stdexec::__mconcat<stdexec::__qq<exec::item_types>>,
193+
__item_types_of_t<_Sequences, _Env...>...
194+
>
195+
>;
196+
};
197+
198+
template <class _Self, class... _Env>
199+
using __items_t = __children_of<_Self, __items_fn_t<_Env...>>;
200+
201+
template <sender_expr_for<merge_t> _Self, class... _Env>
202+
static auto get_item_types(_Self&&, _Env&&...) noexcept {
203+
return __minvoke<__mtry_catch<__q<__items_t>, __q<__error_t>>, _Self, _Env...>();
204+
}
205+
206+
template <sender_expr_for<merge_t> _Self, receiver _Receiver>
207+
static auto subscribe(_Self&& __self, _Receiver __rcvr)
208+
noexcept(__nothrow_callable<__sexpr_apply_t, _Self, __subscribe_fn<_Receiver>>)
209+
-> __sexpr_apply_result_t<_Self, __subscribe_fn<_Receiver>> {
210+
return __sexpr_apply(static_cast<_Self&&>(__self), __subscribe_fn<_Receiver>{__rcvr});
211+
}
212+
};
213+
} // namespace __merge
214+
215+
using __merge::merge_t;
216+
inline constexpr merge_t merge{};
217+
} // namespace exec

0 commit comments

Comments
 (0)