Skip to content

Commit bce62d5

Browse files
committed
implement exec::on() with stdexec::v2::[continue_]on()
1 parent 77026bc commit bce62d5

File tree

5 files changed

+12
-268
lines changed

5 files changed

+12
-268
lines changed

examples/nvexec/maxwell/snr.cuh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ inline constexpr repeat_n_t repeat_n{};
331331
template <class SchedulerT>
332332
[[nodiscard]] bool is_gpu_scheduler(SchedulerT&& scheduler) {
333333
auto snd = ex::just()
334-
| stdexec::v2::continue_on(scheduler, ex::then([] { return nvexec::is_on_gpu(); }));
334+
| exec::on(scheduler, ex::then([] { return nvexec::is_on_gpu(); }));
335335
auto [on_gpu] = stdexec::sync_wait(std::move(snd)).value();
336336
return on_gpu;
337337
}
@@ -344,7 +344,7 @@ auto maxwell_eqs_snr(
344344
fields_accessor accessor,
345345
stdexec::scheduler auto&& computer) {
346346
return ex::just()
347-
| stdexec::v2::continue_on(
347+
| exec::on(
348348
computer,
349349
repeat_n(
350350
n_iterations,
@@ -365,7 +365,7 @@ void run_snr(
365365

366366
auto init =
367367
ex::just()
368-
| stdexec::v2::continue_on(computer, ex::bulk(grid.cells, grid_initializer(dt, accessor)));
368+
| exec::on(computer, ex::bulk(grid.cells, grid_initializer(dt, accessor)));
369369
stdexec::sync_wait(init);
370370

371371
auto snd = maxwell_eqs_snr(dt, time.get(), write_vtk, n_iterations, accessor, computer);

include/exec/on.hpp

Lines changed: 6 additions & 264 deletions
Original file line numberDiff line numberDiff line change
@@ -16,278 +16,20 @@
1616
#pragma once
1717

1818
#include "../stdexec/execution.hpp"
19-
#include "env.hpp"
20-
#include "__detail/__sender_facade.hpp"
2119

2220
namespace exec {
2321
/////////////////////////////////////////////////////////////////////////////
2422
// A scoped version of [execution.senders.adaptors.on]
2523
namespace __on {
26-
using namespace stdexec;
27-
28-
enum class on_kind {
29-
start_on,
30-
continue_on
31-
};
32-
33-
template <on_kind>
34-
struct on_t;
35-
36-
template <class _Env, class _Sender>
37-
struct _ENVIRONMENT_HAS_NO_SCHEDULER_FOR_THE_ON_ADAPTOR_TO_TRANSITION_BACK_TO { };
38-
39-
template <class _Env, class _SchedulerId>
40-
struct __with_sched_env
41-
: __env::__env_join_t<__env::__with<get_scheduler_t, __t<_SchedulerId>>, _Env> { };
42-
43-
template <class _Env, class _Scheduler>
44-
__with_sched_env<_Env, __id<_Scheduler>> __make_env(_Env&& __env, _Scheduler __sched) noexcept {
45-
return {__join_env(__env::__with_(get_scheduler, __sched), (_Env&&) __env)};
46-
}
47-
48-
template <class _Scheduler>
49-
struct __with_sched_kernel : __default_kernel {
50-
_Scheduler __sched_;
51-
52-
__with_sched_kernel(_Scheduler __sched)
53-
: __sched_((_Scheduler&&) __sched) {
54-
}
55-
56-
template <class _Env>
57-
__with_sched_env<_Env, __id<_Scheduler>> get_env(_Env&& __env) noexcept {
58-
return __on::__make_env((_Env&&) __env, __sched_);
59-
}
60-
61-
template <class _Env, class _OtherSchedulerId>
62-
_Env get_env(__with_sched_env<_Env, _OtherSchedulerId> __env) noexcept {
63-
return __env.base();
64-
}
65-
};
66-
67-
template <class _SenderId, class _Scheduler>
68-
struct __with_sched
69-
: __sender_facade<
70-
__with_sched<_SenderId, _Scheduler>,
71-
__t<_SenderId>,
72-
__with_sched_kernel<_Scheduler>> { };
73-
74-
struct __dependent_sender {
75-
using is_sender = void;
76-
using __id = __dependent_sender;
77-
using __t = __dependent_sender;
78-
using completion_signatures = dependent_completion_signatures<no_env>;
79-
};
80-
81-
template <class _SenderId, class _Scheduler>
82-
struct __start_on;
83-
84-
template <class _Sender, class _Scheduler>
85-
using __start_on_t = __t<__start_on<__id<__decay_t<_Sender>>, _Scheduler>>;
86-
87-
template <class _Scheduler>
88-
struct __start_on_kernel : __default_kernel {
89-
_Scheduler __sched_;
90-
91-
explicit __start_on_kernel(_Scheduler __sched)
92-
: __sched_((_Scheduler&&) __sched) {
93-
}
94-
95-
template <class... _Ts>
96-
using __self_t = __mfront<__start_on_kernel, _Ts...>;
97-
98-
template <class _Sender, class _OldScheduler>
99-
auto transform_sender_(_Sender&& __sndr, _OldScheduler __old_sched) {
100-
return stdexec::on(__sched_, (_Sender&&) __sndr) | transfer(__old_sched);
101-
}
102-
103-
template <class _Sender, class _Receiver>
104-
using __new_sender_t = //
105-
decltype(__declval<__self_t<_Sender, _Receiver>&>().transform_sender_(
106-
__declval<_Sender>(),
107-
__declval<__current_scheduler_t<_Receiver>>()));
108-
109-
template <class _Sender>
110-
using __on_sender_t = __copy_cvref_t<_Sender, __start_on_t<_Sender, _Scheduler>>;
111-
112-
template <class _Sender, class _Receiver>
113-
using __diagnostic_t = //
114-
__minvoke< //
115-
_FAILURE_TO_CONNECT_, //
116-
_ENVIRONMENT_HAS_NO_SCHEDULER_FOR_THE_ON_ADAPTOR_TO_TRANSITION_BACK_TO<
117-
env_of_t<_Receiver>,
118-
__on_sender_t<_Sender>>>;
119-
120-
template <class _Sender, class _Receiver>
121-
static auto __transform_sender_result() {
122-
if constexpr (__mvalid<__new_sender_t, _Sender, _Receiver>) {
123-
return (__new_sender_t<_Sender, _Receiver>(*)()) nullptr;
124-
} else if constexpr (same_as<env_of_t<_Receiver>, no_env>) {
125-
return (__dependent_sender(*)()) nullptr;
126-
} else {
127-
return (__diagnostic_t<_Sender, _Receiver>(*)()) nullptr;
128-
}
129-
}
130-
131-
template <class _Sender, class _Receiver>
132-
using __result_t = decltype(__transform_sender_result<_Sender, _Receiver>()());
133-
134-
template <class _Sender, class _Receiver>
135-
auto transform_sender(_Sender&& __sndr, __ignore, _Receiver& __rcvr)
136-
-> __result_t<_Sender, _Receiver> {
137-
if constexpr (__mvalid<__new_sender_t, _Sender, _Receiver>) {
138-
auto __sched = get_scheduler(stdexec::get_env(__rcvr));
139-
return transform_sender_((_Sender&&) __sndr, __sched);
140-
} else {
141-
return {};
142-
}
143-
}
24+
struct on_t
25+
: stdexec::v2::on_t
26+
, stdexec::v2::continue_on_t {
27+
using stdexec::v2::on_t::operator();
28+
using stdexec::v2::continue_on_t::operator();
14429
};
14530

146-
template <class _SenderId, class _Scheduler>
147-
struct __start_on {
148-
using __base = //
149-
stdexec::__t< __sender_facade<
150-
__start_on<_SenderId, _Scheduler>,
151-
stdexec::__t<_SenderId>,
152-
__start_on_kernel<_Scheduler>>>;
153-
154-
struct __t : __base {
155-
using __base::__base;
156-
};
157-
};
158-
159-
template <>
160-
struct on_t<on_kind::start_on> {
161-
template <scheduler _Scheduler, sender _Sender>
162-
requires constructible_from<__decay_t<_Sender>, _Sender>
163-
auto operator()(_Scheduler __sched, _Sender&& __sndr) const
164-
-> __start_on_t<_Sender, _Scheduler> {
165-
// connect-based customization will remove the need for this check
166-
using __has_customizations = __call_result_t<__has_algorithm_customizations_t, _Scheduler>;
167-
static_assert(
168-
!__has_customizations{},
169-
"For now the default exec::on implementation doesn't support scheduling "
170-
"onto schedulers that customize algorithms.");
171-
return {(_Sender&&) __sndr, (_Scheduler&&) __sched};
172-
}
173-
};
174-
175-
template <class _SenderId, class _Scheduler, class _Closure>
176-
struct __continue_on;
177-
178-
template <class _Sender, class _Scheduler, class _Closure>
179-
using __continue_on_t = __t<__continue_on<__id<__decay_t<_Sender>>, _Scheduler, _Closure>>;
180-
181-
template <class _Scheduler, class _Closure>
182-
struct __continue_on_kernel : __default_kernel {
183-
_Scheduler __sched_;
184-
_Closure __closure_;
185-
186-
__continue_on_kernel(_Scheduler __sched, _Closure __closure)
187-
: __sched_((_Scheduler&&) __sched)
188-
, __closure_((_Closure&&) __closure) {
189-
}
190-
191-
template <class... _Ts>
192-
using __self_t = __mfront<__continue_on_kernel, _Ts...>;
193-
194-
template <class _Sender, class _OldScheduler>
195-
auto transform_sender_(_Sender&& __sndr, _OldScheduler __old_sched) {
196-
using __sender_t = __t<__with_sched<__id<__decay_t<_Sender>>, _OldScheduler>>;
197-
return __sender_t{(_Sender&&) __sndr, __old_sched} | transfer(__sched_)
198-
| (__copy_cvref_t<_Sender, _Closure>&&) __closure_ | transfer(__old_sched);
199-
}
200-
201-
template <class _Sender, class _Receiver>
202-
using __new_sender_t = //
203-
decltype(__declval<__self_t<_Sender, _Receiver>&>().transform_sender_(
204-
__declval<_Sender>(),
205-
__declval<__current_scheduler_t<_Receiver>>()));
206-
207-
template <class _Sender>
208-
using __on_sender_t = __copy_cvref_t<_Sender, __continue_on_t<_Sender, _Scheduler, _Closure>>;
209-
210-
template <class _Sender, class _Receiver>
211-
using __diagnostic_t = //
212-
__minvoke< //
213-
_FAILURE_TO_CONNECT_, //
214-
_ENVIRONMENT_HAS_NO_SCHEDULER_FOR_THE_ON_ADAPTOR_TO_TRANSITION_BACK_TO<
215-
env_of_t<_Receiver>,
216-
__on_sender_t<_Sender>>>;
217-
218-
template <class _Sender, class _Receiver>
219-
static auto __transform_sender_result() {
220-
if constexpr (__mvalid<__new_sender_t, _Sender, _Receiver>) {
221-
return (__new_sender_t<_Sender, _Receiver>(*)()) nullptr;
222-
} else if constexpr (same_as<env_of_t<_Receiver>, no_env>) {
223-
return (__dependent_sender(*)()) nullptr;
224-
} else {
225-
return (__diagnostic_t<_Sender, _Receiver>(*)()) nullptr;
226-
}
227-
}
228-
229-
template <class _Sender, class _Receiver>
230-
using __result_t = decltype(__transform_sender_result<_Sender, _Receiver>()());
231-
232-
template <class _Sender, class _Receiver>
233-
auto transform_sender(_Sender&& __sndr, __ignore, _Receiver& __rcvr)
234-
-> __result_t<_Sender, _Receiver> {
235-
if constexpr (__mvalid<__new_sender_t, _Sender, _Receiver>) {
236-
auto __sched = get_scheduler(stdexec::get_env(__rcvr));
237-
return transform_sender_((_Sender&&) __sndr, __sched);
238-
} else {
239-
return {};
240-
}
241-
}
242-
243-
template <class _Env>
244-
__with_sched_env<_Env, __id<_Scheduler>> get_env(_Env&& __env) noexcept {
245-
return __on::__make_env((_Env&&) __env, __sched_);
246-
}
247-
};
248-
249-
template <class _SenderId, class _Scheduler, class _Closure>
250-
struct __continue_on {
251-
using __base = //
252-
stdexec::__t<__sender_facade<
253-
__continue_on<_SenderId, _Scheduler, _Closure>,
254-
stdexec::__t<_SenderId>,
255-
__continue_on_kernel<_Scheduler, _Closure>>>;
256-
257-
struct __t : __base {
258-
using __base::__base;
259-
};
260-
};
261-
262-
template <>
263-
struct on_t<on_kind::continue_on> {
264-
template <sender _Sender, scheduler _Scheduler, __sender_adaptor_closure_for<_Sender> _Closure>
265-
requires constructible_from<__decay_t<_Sender>, _Sender>
266-
auto operator()(_Sender&& __sndr, _Scheduler __sched, _Closure __closure) const
267-
-> __continue_on_t<_Sender, _Scheduler, _Closure> {
268-
return {(_Sender&&) __sndr, (_Scheduler&&) __sched, (_Closure&&) __closure};
269-
}
270-
271-
template <scheduler _Scheduler, __sender_adaptor_closure _Closure>
272-
auto operator()(_Scheduler __sched, _Closure __closure) const
273-
-> __binder_back<on_t, _Scheduler, _Closure> {
274-
return {
275-
{},
276-
{},
277-
{(_Scheduler&&) __sched, (_Closure&&) __closure}
278-
};
279-
}
280-
};
281-
282-
struct __on_t
283-
: on_t<on_kind::start_on>
284-
, on_t<on_kind::continue_on> {
285-
using on_t<on_kind::start_on>::operator();
286-
using on_t<on_kind::continue_on>::operator();
287-
};
28831
} // namespace __on
28932

290-
using __on::on_kind;
29133
using __on::on_t;
292-
inline constexpr __on::__on_t on{};
34+
inline constexpr on_t on{};
29335
} // namespace exec

test/exec/test_on.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ TEST_CASE("exec::on keeps error_types from scheduler's sender", "[adaptors][exec
183183
exec::on(sched1, ex::just(1)) | _with_scheduler());
184184
check_err_types<type_array<std::exception_ptr&&>>(
185185
exec::on(sched2, ex::just(2)) | _with_scheduler());
186-
check_err_types<type_array<std::exception_ptr&&, int&&>>(
186+
check_err_types<type_array<int&&, std::exception_ptr&&>>(
187187
exec::on(sched3, ex::just(3)) | _with_scheduler());
188188
}
189189

test/stdexec/algos/adaptors/test_then.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <catch2/catch.hpp>
1818
#include <stdexec/execution.hpp>
1919
#include <exec/on.hpp>
20+
#include <exec/env.hpp>
2021
#include <test_common/schedulers.hpp>
2122
#include <test_common/receivers.hpp>
2223
#include <test_common/senders.hpp>

test/tbbexec/test_tbb_thread_pool.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include <test_common/schedulers.hpp>
2525
#include <exec/on.hpp>
26+
#include <exec/env.hpp>
2627
#include <exec/inline_scheduler.hpp>
2728

2829
#include <tbbexec/tbb_thread_pool.hpp>

0 commit comments

Comments
 (0)