xref: /openbmc/sdbusplus/include/sdbusplus/async/stdexec/__detail/__transfer_just.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 "__basic_sender.hpp"
22 #include "__concepts.hpp"
23 #include "__continues_on.hpp"
24 #include "__domain.hpp"
25 #include "__env.hpp"
26 #include "__just.hpp"
27 #include "__meta.hpp"
28 #include "__schedule_from.hpp"
29 #include "__schedulers.hpp"
30 #include "__sender_introspection.hpp"
31 #include "__tag_invoke.hpp"
32 #include "__transform_sender.hpp"
33 #include "__tuple.hpp"
34 
35 STDEXEC_PRAGMA_PUSH()
36 STDEXEC_PRAGMA_IGNORE_GNU("-Wmissing-braces")
37 
38 namespace stdexec
39 {
40 /////////////////////////////////////////////////////////////////////////////
41 // [execution.senders.transfer_just]
42 namespace __transfer_just
43 {
44 // This is a helper for finding legacy cusutomizations of transfer_just.
__transfer_just_tag_invoke()45 inline auto __transfer_just_tag_invoke()
46 {
47     return []<class... _Ts>(
48                _Ts&&... __ts) -> tag_invoke_result_t<transfer_just_t, _Ts...> {
49         return tag_invoke(transfer_just, static_cast<_Ts&&>(__ts)...);
50     };
51 }
52 
53 template <class _Env>
__make_transform_fn(const _Env &)54 auto __make_transform_fn(const _Env&)
55 {
56     return [&]<class _Scheduler, class... _Values>(_Scheduler&& __sched,
57                                                    _Values&&... __vals) {
58         return continues_on(just(static_cast<_Values&&>(__vals)...),
59                             static_cast<_Scheduler&&>(__sched));
60     };
61 }
62 
63 template <class _Env>
__transform_sender_fn(const _Env & __env)64 auto __transform_sender_fn(const _Env& __env)
65 {
66     return [&]<class _Data>(__ignore, _Data&& __data) {
67         return __data.apply(__make_transform_fn(__env),
68                             static_cast<_Data&&>(__data));
69     };
70 }
71 
72 struct __legacy_customization_fn
73 {
74     template <class _Data>
operator ()stdexec::__transfer_just::__legacy_customization_fn75     auto operator()(_Data&& __data) const
76         -> decltype(__data.apply(__transfer_just_tag_invoke(),
77                                  static_cast<_Data&&>(__data)))
78     {
79         return __data.apply(__transfer_just_tag_invoke(),
80                             static_cast<_Data&&>(__data));
81     }
82 };
83 
84 struct transfer_just_t
85 {
86     using _Data = __0;
87     using __legacy_customizations_t = //
88         __types<__legacy_customization_fn(_Data)>;
89 
90     template <scheduler _Scheduler, __movable_value... _Values>
operator ()stdexec::__transfer_just::transfer_just_t91     auto operator()(_Scheduler&& __sched, _Values&&... __vals) const
92         -> __well_formed_sender auto
93     {
94         auto __domain = query_or(get_domain, __sched, default_domain());
95         return stdexec::transform_sender(
96             __domain, __make_sexpr<transfer_just_t>(
97                           __tuple{static_cast<_Scheduler&&>(__sched),
98                                   static_cast<_Values&&>(__vals)...}));
99     }
100 
101     template <class _Sender, class _Env>
transform_senderstdexec::__transfer_just::transfer_just_t102     static auto transform_sender(_Sender&& __sndr, const _Env& __env)
103     {
104         return __sexpr_apply(static_cast<_Sender&&>(__sndr),
105                              __transform_sender_fn(__env));
106     }
107 };
108 
__make_env_fn()109 inline auto __make_env_fn() noexcept
110 {
111     return []<class _Scheduler>(const _Scheduler& __sched,
112                                 const auto&...) noexcept {
113         using _Env = __t<__schfr::__environ<__id<_Scheduler>>>;
114         return _Env{__sched};
115     };
116 }
117 
118 struct __transfer_just_impl : __sexpr_defaults
119 {
120     static constexpr auto get_attrs = //
121         []<class _Data>(const _Data& __data) noexcept {
122             return __data.apply(__make_env_fn(), __data);
123         };
124 
125     static constexpr auto get_completion_signatures = //
126         []<class _Sender>(_Sender&&) noexcept         //
127         -> __completion_signatures_of_t<              //
128             transform_sender_result_t<default_domain, _Sender, empty_env>> {};
129 };
130 } // namespace __transfer_just
131 
132 using __transfer_just::transfer_just_t;
133 inline constexpr transfer_just_t transfer_just{};
134 
135 template <>
136 struct __sexpr_impl<transfer_just_t> : __transfer_just::__transfer_just_impl
137 {};
138 } // namespace stdexec
139 
140 STDEXEC_PRAGMA_POP()
141