1 /*
2  * Copyright (c) 2021-2024 NVIDIA Corporation
3  *
4  * Licensed under the Apache License Version 2.0 with LLVM Exceptions
5  * (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  *
8  *   https://llvm.org/LICENSE.txt
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include "__execution_fwd.hpp"
19 
20 // include these after __execution_fwd.hpp
21 #include "__basic_sender.hpp"
22 #include "__concepts.hpp"
23 #include "__env.hpp"
24 #include "__meta.hpp"
25 #include "__schedule_from.hpp"
26 #include "__schedulers.hpp"
27 #include "__sender_adaptor_closure.hpp"
28 #include "__sender_introspection.hpp"
29 #include "__senders.hpp"
30 #include "__tag_invoke.hpp"
31 #include "__transform_sender.hpp"
32 #include "__type_traits.hpp"
33 
34 #include <utility>
35 
36 namespace stdexec
37 {
38 /////////////////////////////////////////////////////////////////////////////
39 // [execution.senders.adaptors.continue_on]
40 namespace __continue_on
41 {
42 using __schfr::__environ;
43 
44 template <class _Env>
45 using __scheduler_t = __result_of<get_completion_scheduler<set_value_t>, _Env>;
46 
47 template <class _Sender>
48 using __lowered_t = //
49     __result_of<schedule_from, __scheduler_t<__data_of<_Sender>>,
50                 __child_of<_Sender>>;
51 
52 struct continue_on_t
53 {
54     template <sender _Sender, scheduler _Scheduler>
operator ()stdexec::__continue_on::continue_on_t55     auto operator()(_Sender&& __sndr,
56                     _Scheduler&& __sched) const -> __well_formed_sender auto
57     {
58         auto __domain = __get_early_domain(__sndr);
59         using _Env = __t<__environ<__id<__decay_t<_Scheduler>>>>;
60         return stdexec::transform_sender(
61             __domain, __make_sexpr<continue_on_t>(
62                           _Env{{static_cast<_Scheduler&&>(__sched)}},
63                           static_cast<_Sender&&>(__sndr)));
64     }
65 
66     template <scheduler _Scheduler>
67     STDEXEC_ATTRIBUTE((always_inline))
operator ()stdexec::__continue_on::continue_on_t68     auto operator()(_Scheduler&& __sched) const
69         -> __binder_back<continue_on_t, __decay_t<_Scheduler>>
70     {
71         return {{static_cast<_Scheduler&&>(__sched)}, {}, {}};
72     }
73 
74     //////////////////////////////////////////////////////////////////////////////////////////////
75     using _Env = __0;
76     using _Sender = __1;
77     using __legacy_customizations_t = //
78         __types<tag_invoke_t(continue_on_t,
79                              get_completion_scheduler_t<set_value_t>(
80                                  get_env_t(const _Sender&)),
81                              _Sender,
82                              get_completion_scheduler_t<set_value_t>(_Env)),
83                 tag_invoke_t(continue_on_t, _Sender,
84                              get_completion_scheduler_t<set_value_t>(_Env))>;
85 
86     template <class _Env>
__transform_sender_fnstdexec::__continue_on::continue_on_t87     static auto __transform_sender_fn(const _Env&)
88     {
89         return [&]<class _Data, class _Child>(__ignore, _Data&& __data,
90                                               _Child&& __child) {
91             auto __sched = get_completion_scheduler<set_value_t>(__data);
92             return schedule_from(std::move(__sched),
93                                  static_cast<_Child&&>(__child));
94         };
95     }
96 
97     template <class _Sender, class _Env>
transform_senderstdexec::__continue_on::continue_on_t98     static auto transform_sender(_Sender&& __sndr, const _Env& __env)
99     {
100         return __sexpr_apply(static_cast<_Sender&&>(__sndr),
101                              __transform_sender_fn(__env));
102     }
103 };
104 
105 struct __continue_on_impl : __sexpr_defaults
106 {
107     static constexpr auto get_attrs = //
108         []<class _Data, class _Child>(
109             const _Data& __data,
110             const _Child& __child) noexcept -> decltype(auto) {
111         return __env::__join(__data, stdexec::get_env(__child));
112     };
113 
114     static constexpr auto get_completion_signatures = //
115         []<class _Sender>(_Sender&&) noexcept         //
116         -> __completion_signatures_of_t<              //
117             transform_sender_result_t<default_domain, _Sender, empty_env>> {};
118 };
119 } // namespace __continue_on
120 
121 using __continue_on::continue_on_t;
122 inline constexpr continue_on_t continue_on{};
123 
124 using transfer_t = continue_on_t;
125 inline constexpr transfer_t transfer{};
126 
127 template <>
128 struct __sexpr_impl<continue_on_t> : __continue_on::__continue_on_impl
129 {};
130 } // namespace stdexec
131