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 "__concepts.hpp"
22 #include "__diagnostics.hpp"
23 #include "__domain.hpp"
24 #include "__env.hpp"
25 #include "__let.hpp"
26 #include "__meta.hpp"
27 #include "__schedulers.hpp"
28 #include "__senders_core.hpp"
29 #include "__tag_invoke.hpp"
30 #include "__transform_sender.hpp"
31 #include "__utility.hpp"
32 
33 namespace stdexec
34 {
35 namespace __detail
36 {
37 template <class _Ty, class = __name_of<__decay_t<_Ty>>>
38 struct __always
39 {
40     _Ty __val_;
41 
operator ()stdexec::__detail::__always42     auto operator()() noexcept -> _Ty
43     {
44         return static_cast<_Ty&&>(__val_);
45     }
46 };
47 
48 template <class _Ty>
49 __always(_Ty) -> __always<_Ty>;
50 } // namespace __detail
51 
52 /////////////////////////////////////////////////////////////////////////////
53 // [execution.senders.adaptors.start_on]
54 namespace __start_on
55 {
56 struct start_on_t
57 {
58     using _Sender = __1;
59     using _Scheduler = __0;
60     using __legacy_customizations_t =
61         __types<tag_invoke_t(start_on_t, _Scheduler, _Sender)>;
62 
63     template <scheduler _Scheduler, sender _Sender>
operator ()stdexec::__start_on::start_on_t64     auto operator()(_Scheduler&& __sched,
65                     _Sender&& __sndr) const -> __well_formed_sender auto
66     {
67         auto __domain = query_or(get_domain, __sched, default_domain());
68         return stdexec::transform_sender(
69             __domain,
70             __make_sexpr<start_on_t>(static_cast<_Scheduler&&>(__sched),
71                                      static_cast<_Sender&&>(__sndr)));
72     }
73 
74     template <class _Env>
75     STDEXEC_ATTRIBUTE((always_inline))
__transform_env_fnstdexec::__start_on::start_on_t76     static auto __transform_env_fn(_Env&& __env) noexcept
77     {
78         return [&](__ignore, auto __sched, __ignore) noexcept {
79             return __detail::__mkenv_sched(static_cast<_Env&&>(__env), __sched);
80         };
81     }
82 
83     template <class _Sender, class _Env>
transform_envstdexec::__start_on::start_on_t84     static auto transform_env(const _Sender& __sndr, _Env&& __env) noexcept
85     {
86         return __sexpr_apply(__sndr,
87                              __transform_env_fn(static_cast<_Env&&>(__env)));
88     }
89 
90     template <class _Sender, class _Env>
transform_senderstdexec::__start_on::start_on_t91     static auto transform_sender(_Sender&& __sndr, const _Env&)
92     {
93         return __sexpr_apply(
94             static_cast<_Sender&&>(__sndr),
95             []<class _Data, class _Child>(__ignore, _Data&& __data,
96                                           _Child&& __child) {
97                 return let_value(
98                     schedule(__data),
99                     __detail::__always{static_cast<_Child&&>(__child)});
100             });
101     }
102 };
103 } // namespace __start_on
104 
105 using __start_on::start_on_t;
106 inline constexpr start_on_t start_on{};
107 
108 using on_t = start_on_t;
109 inline constexpr on_t on{};
110 
111 template <>
112 struct __sexpr_impl<start_on_t> : __sexpr_defaults
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         return {};
119     };
120 };
121 } // namespace stdexec
122