xref: /openbmc/sdbusplus/include/sdbusplus/async/stdexec/__detail/__starts_on.hpp (revision 36137e09614746b13603b5fbae79e6f70819c46b)
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 //! Constant function object always returning `__val_`.
38 template <class _Ty, class = __name_of<__decay_t<_Ty>>>
39 struct __always
40 {
41     _Ty __val_;
42 
operator ()stdexec::__detail::__always43     auto operator()() noexcept -> _Ty
44     {
45         return static_cast<_Ty&&>(__val_);
46     }
47 };
48 
49 template <class _Ty>
50 __always(_Ty) -> __always<_Ty>;
51 } // namespace __detail
52 
53 /////////////////////////////////////////////////////////////////////////////
54 // [execution.senders.adaptors.starts_on]
55 namespace __starts_on_ns
56 {
57 struct starts_on_t
58 {
59     using _Sender = __1;
60     using _Scheduler = __0;
61     using __legacy_customizations_t =
62         __types<tag_invoke_t(starts_on_t, _Scheduler, _Sender)>;
63 
64     template <scheduler _Scheduler, sender _Sender>
operator ()stdexec::__starts_on_ns::starts_on_t65     auto operator()(_Scheduler&& __sched, _Sender&& __sndr) const
66         -> __well_formed_sender auto
67     {
68         auto __domain = query_or(get_domain, __sched, default_domain());
69         return stdexec::transform_sender(
70             __domain,
71             __make_sexpr<starts_on_t>(static_cast<_Scheduler&&>(__sched),
72                                       static_cast<_Sender&&>(__sndr)));
73     }
74 
75     template <class _Env>
76     STDEXEC_ATTRIBUTE((always_inline))
__transform_env_fnstdexec::__starts_on_ns::starts_on_t77     static auto __transform_env_fn(_Env&& __env) noexcept
78     {
79         return [&](__ignore, auto __sched, __ignore) noexcept {
80             return __detail::__mkenv_sched(static_cast<_Env&&>(__env), __sched);
81         };
82     }
83 
84     template <class _Sender, class _Env>
transform_envstdexec::__starts_on_ns::starts_on_t85     static auto transform_env(const _Sender& __sndr, _Env&& __env) noexcept
86     {
87         return __sexpr_apply(__sndr,
88                              __transform_env_fn(static_cast<_Env&&>(__env)));
89     }
90 
91     template <class _Sender, class _Env>
transform_senderstdexec::__starts_on_ns::starts_on_t92     static auto transform_sender(_Sender&& __sndr, const _Env&)
93     {
94         return __sexpr_apply(
95             static_cast<_Sender&&>(__sndr),
96             []<class _Data, class _Child>(__ignore, _Data&& __data,
97                                           _Child&& __child) {
98                 // This is the heart of starts_on: It uses `let_value` to
99                 // schedule `__child` on the given scheduler:
100                 return let_value(
101                     schedule(__data),
102                     __detail::__always{static_cast<_Child&&>(__child)});
103             });
104     }
105 };
106 } // namespace __starts_on_ns
107 
108 using __starts_on_ns::starts_on_t;
109 inline constexpr starts_on_t starts_on{};
110 
111 using on_t = starts_on_t;
112 inline constexpr starts_on_t on{};
113 
114 using start_on_t = starts_on_t;
115 inline constexpr starts_on_t start_on{};
116 
117 template <>
118 struct __sexpr_impl<starts_on_t> : __sexpr_defaults
119 {
120     static constexpr auto get_completion_signatures = //
121         []<class _Sender>(_Sender&&) noexcept         //
122         -> __completion_signatures_of_t<              //
123             transform_sender_result_t<default_domain, _Sender, empty_env>> {
124         return {};
125     };
126 };
127 } // namespace stdexec
128