Skip to content

Commit 7d957d0

Browse files
committed
make the trailing on algorithm update the env properly
1 parent 9082d76 commit 7d957d0

File tree

4 files changed

+42
-52
lines changed

4 files changed

+42
-52
lines changed

include/stdexec/__detail/__diagnostics.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,22 +206,22 @@ namespace stdexec {
206206
using __stopped_types = __dependent_sender_error;
207207
};
208208

209-
template <class _What, class... _With>
209+
template <class... _What>
210210
struct __not_a_sender {
211211
using sender_concept = sender_t;
212212

213213
template <class Self>
214214
constexpr auto get_completion_signatures(Self&&) const noexcept {
215-
return __mexception<_What, _With...>();
215+
return __mexception<_What...>();
216216
}
217217
};
218218

219-
template <class _What, class... _With>
219+
template <class... _What>
220220
struct __not_a_scheduler {
221221
using scheduler_concept = scheduler_t;
222222

223223
auto schedule() noexcept {
224-
return __not_a_sender<_What, _With...>{};
224+
return __not_a_sender<_What...>{};
225225
}
226226

227227
constexpr bool operator==(__not_a_scheduler) const noexcept {

include/stdexec/__detail/__meta.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ namespace stdexec {
248248

249249
using __msuccess = int;
250250

251-
template <class _What, class... _With>
251+
template <class... _What>
252252
struct _WARNING_ { };
253253

254254
template <class... _What>

include/stdexec/__detail/__on.hpp

Lines changed: 36 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -28,43 +28,18 @@
2828
#include "__senders_core.hpp"
2929
#include "__sender_adaptor_closure.hpp"
3030
#include "__sender_introspection.hpp"
31-
#include "__type_traits.hpp"
3231
#include "__utility.hpp"
32+
#include "__write_env.hpp"
3333

3434
namespace stdexec {
3535
/////////////////////////////////////////////////////////////////////////////
3636
// [execution.senders.adaptors.on]
3737
namespace __on {
38-
inline constexpr __mstring __on_context = "In stdexec::on(Scheduler, Sender)..."_mstr;
39-
inline constexpr __mstring __no_scheduler_diag =
40-
"stdexec::on() requires a scheduler to transition back to."_mstr;
41-
inline constexpr __mstring __no_scheduler_details =
42-
"The provided environment lacks a value for the get_scheduler() query."_mstr;
43-
44-
template <
45-
__mstring _Context = __on_context,
46-
__mstring _Diagnostic = __no_scheduler_diag,
47-
__mstring _Details = __no_scheduler_details
48-
>
49-
struct _CANNOT_RESTORE_EXECUTION_CONTEXT_AFTER_ON_ { };
50-
5138
struct on_t;
5239

53-
template <class _Sender, class _Env>
54-
struct __no_scheduler_in_environment {
55-
using sender_concept = sender_t;
56-
57-
STDEXEC_EXPLICIT_THIS_BEGIN(auto get_completion_signatures)(
58-
this const __no_scheduler_in_environment&,
59-
const auto&) noexcept {
60-
return __mexception<
61-
_CANNOT_RESTORE_EXECUTION_CONTEXT_AFTER_ON_<>,
62-
_WITH_SENDER_<_Sender>,
63-
_WITH_ENVIRONMENT_<_Env>
64-
>{};
65-
}
66-
STDEXEC_EXPLICIT_THIS_END(get_completion_signatures)
67-
};
40+
struct _CANNOT_RESTORE_THE_EXECUTION_CONTEXT_AFTER_ON;
41+
struct _THE_ENVIRONMENT_OF_THE_RECEIVER_DOES_NOT_HAVE_A_SCHEDULER_FOR_ON_TO_RETURN_TO;
42+
struct _THE_PREDECESSOR_SENDER_DOES_NOT_KNOW_THE_SCHEDULER_ON_WHICH_IT_COMPLETES;
6843

6944
template <class _Scheduler, class _Closure>
7045
struct __on_data {
@@ -73,7 +48,8 @@ namespace stdexec {
7348
};
7449

7550
template <class _Scheduler, class _Closure>
76-
__on_data(_Scheduler, _Closure) -> __on_data<_Scheduler, _Closure>;
51+
STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE __on_data(_Scheduler, _Closure) //
52+
->__on_data<_Scheduler, _Closure>;
7753

7854
////////////////////////////////////////////////////////////////////////////////////////////////
7955
struct on_t {
@@ -99,30 +75,31 @@ namespace stdexec {
9975
}
10076

10177
template <class _Sender, class _OldSched, class _NewSched>
102-
static auto __reschedule(
103-
_Sender&& __sndr,
104-
[[maybe_unused]] _OldSched&& __old_sched,
105-
_NewSched&& __new_sched) {
106-
// return continues_on(
107-
// write_env(static_cast<_Sender&&>(__sndr), __sched_env{__old_sched}),
108-
// static_cast<_NewSched&&>(__new_sched));
109-
return continues_on(static_cast<_Sender&&>(__sndr), static_cast<_NewSched&&>(__new_sched));
78+
static auto __reschedule(_Sender&& __sndr, _OldSched&& __old_sched, _NewSched&& __new_sched) {
79+
return continues_on(
80+
write_env(static_cast<_Sender&&>(__sndr), __sched_env{__old_sched}),
81+
static_cast<_NewSched&&>(__new_sched));
11082
}
11183

11284
template <class _Sender, class _Env>
11385
STDEXEC_ATTRIBUTE(always_inline)
11486
static auto __transform_sender_fn(const _Env& __env) noexcept {
11587
return [&]<class _Data, class _Child>(__ignore, _Data&& __data, _Child&& __child) {
116-
// If __is_root_env<_Env> is true, then this sender has no parent, so there is
117-
// no need to restore the execution context. We can use the inline scheduler
118-
// as the scheduler if __env does not have one.
119-
using __end_sched_t = __if_c<
120-
__is_root_env<_Env>,
121-
inline_scheduler,
122-
__not_a_scheduler<__no_scheduler_in_environment<_Sender, _Env>>
123-
>;
12488

12589
if constexpr (scheduler<_Data>) {
90+
using __not_a_scheduler = stdexec::__not_a_scheduler<
91+
_WHAT_<>(_CANNOT_RESTORE_THE_EXECUTION_CONTEXT_AFTER_ON),
92+
_WHY_(_THE_ENVIRONMENT_OF_THE_RECEIVER_DOES_NOT_HAVE_A_SCHEDULER_FOR_ON_TO_RETURN_TO),
93+
_WHERE_(_IN_ALGORITHM_, on_t),
94+
_WITH_ENVIRONMENT_<_Env>,
95+
_WITH_SENDER_<_Child>
96+
>;
97+
98+
// If __is_root_env<_Env> is true, then this sender has no parent, so there is
99+
// no need to restore the execution context. We can use the inline scheduler
100+
// as the scheduler if __env does not have one.
101+
using __end_sched_t = __if_c<__is_root_env<_Env>, inline_scheduler, __not_a_scheduler>;
102+
126103
// This branch handles the case where `on` was called like `on(sch, sndr)`. In
127104
// this case, we find the old scheduler by looking in the receiver's
128105
// environment.
@@ -132,6 +109,19 @@ namespace stdexec {
132109
starts_on(static_cast<_Data&&>(__data), static_cast<_Child&&>(__child)),
133110
static_cast<decltype(__old)&&>(__old));
134111
} else {
112+
using __not_a_scheduler = stdexec::__not_a_scheduler<
113+
_WHAT_<>(_CANNOT_RESTORE_THE_EXECUTION_CONTEXT_AFTER_ON),
114+
_WHY_(_THE_PREDECESSOR_SENDER_DOES_NOT_KNOW_THE_SCHEDULER_ON_WHICH_IT_COMPLETES),
115+
_WHERE_(_IN_ALGORITHM_, on_t),
116+
_WITH_SENDER_<_Child>,
117+
_WITH_ENVIRONMENT_<_Env>
118+
>;
119+
120+
// If __is_root_env<_Env> is true, then this sender has no parent, so there is
121+
// no need to restore the execution context. We can use the inline scheduler
122+
// as the scheduler if __env does not have one.
123+
using __end_sched_t = __if_c<__is_root_env<_Env>, inline_scheduler, __not_a_scheduler>;
124+
135125
// This branch handles the case where `on` was called like `sndr | on(sch,
136126
// clsur)`. In this case, __child is a predecessor sender, so the scheduler we
137127
// want to restore is the completion scheduler of __child.

test/stdexec/algos/adaptors/test_on3.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ namespace {
126126
auto snd = ex::get_scheduler() | ex::on(inline_scheduler{}, probe_env())
127127
| ex::then([]<class Env>(Env) noexcept {
128128
using Sched = ex::__call_result_t<ex::get_scheduler_t, Env>;
129-
static_assert(ex::same_as<Sched, ex::run_loop::scheduler>);
129+
static_assert(ex::same_as<Sched, inline_scheduler>);
130130
})
131131
| probe_env() | ex::then([]<class Env>(Env) noexcept {
132132
using Sched = ex::__call_result_t<ex::get_scheduler_t, Env>;

0 commit comments

Comments
 (0)