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 "../stdexec/execution.hpp" 19 20 STDEXEC_PRAGMA_PUSH() 21 STDEXEC_PRAGMA_IGNORE_EDG(1302) 22 23 namespace exec { 24 template <class _Tag, class _Value> 25 using with_t = stdexec::prop<_Tag, _Value>; 26 27 namespace __envs { 28 struct __with_t { 29 template <class _Tag, class _Value> operator ()exec::__envs::__with_t30 constexpr auto operator()(_Tag, _Value&& __val) const { 31 return stdexec::prop{_Tag(), static_cast<_Value&&>(__val)}; 32 } 33 }; 34 35 struct __without_t { 36 template <class _Env, class _Tag> operator ()exec::__envs::__without_t37 constexpr auto operator()(_Env&& __env, _Tag) const -> decltype(auto) { 38 return stdexec::__env::__without(static_cast<_Env&&>(__env), _Tag()); 39 } 40 }; 41 42 // For making an environment from key/value pairs and optionally 43 // another environment. 44 struct __make_env_t { 45 template < 46 stdexec::__nothrow_move_constructible _Base, 47 stdexec::__nothrow_move_constructible _Env 48 > operator ()exec::__envs::__make_env_t49 constexpr auto operator()(_Base&& __base, _Env&& __env) const noexcept 50 -> stdexec::__join_env_t<_Env, _Base> { 51 return stdexec::__env::__join(static_cast<_Env&&>(__env), static_cast<_Base&&>(__base)); 52 } 53 54 template <stdexec::__nothrow_move_constructible _Env> operator ()exec::__envs::__make_env_t55 constexpr auto operator()(_Env&& __env) const noexcept -> _Env { 56 return static_cast<_Env&&>(__env); 57 } 58 }; 59 } // namespace __envs 60 61 inline constexpr __envs::__with_t with{}; 62 inline constexpr __envs::__without_t without{}; 63 inline constexpr __envs::__make_env_t make_env{}; 64 65 template <class... _Ts> 66 using make_env_t = stdexec::__result_of<make_env, _Ts...>; 67 68 namespace __read_with_default { 69 using namespace stdexec; 70 71 struct read_with_default_t; 72 73 template <class _Tag, class _DefaultId, class _ReceiverId> 74 struct __operation { 75 using _Default = stdexec::__t<_DefaultId>; 76 using _Receiver = stdexec::__t<_ReceiverId>; 77 78 struct __t : __immovable { 79 using __id = __operation; 80 81 STDEXEC_ATTRIBUTE(no_unique_address) _Default __default_; 82 _Receiver __rcvr_; 83 startexec::__read_with_default::__operation::__t84 constexpr void start() & noexcept { 85 STDEXEC_TRY { 86 if constexpr (__callable<_Tag, env_of_t<_Receiver>>) { 87 const auto& __env = get_env(__rcvr_); 88 stdexec::set_value(std::move(__rcvr_), _Tag{}(__env)); 89 } else { 90 stdexec::set_value(std::move(__rcvr_), std::move(__default_)); 91 } 92 } 93 STDEXEC_CATCH_ALL { 94 stdexec::set_error(std::move(__rcvr_), std::current_exception()); 95 } 96 } 97 }; 98 }; 99 100 template <class _Tag, class _Default, class _Receiver> 101 using __operation_t = __t<__operation<_Tag, __id<_Default>, __id<_Receiver>>>; 102 103 template <class _Tag, class _Default> 104 struct __sender { 105 using __id = __sender; 106 using __t = __sender; 107 using sender_concept = stdexec::sender_t; 108 STDEXEC_ATTRIBUTE(no_unique_address) _Default __default_; 109 110 template <class _Env> 111 using __value_t = 112 __minvoke<__with_default<__mbind_back_q<__call_result_t, _Env>, _Default>, _Tag>; 113 template <class _Env> 114 using __default_t = __if_c<__callable<_Tag, _Env>, __ignore, _Default>; 115 116 template <class _Env> 117 using __completions_t = 118 completion_signatures<set_value_t(__value_t<_Env>), set_error_t(std::exception_ptr)>; 119 120 template <__decays_to<__sender> _Self, class _Receiver> 121 requires receiver_of<_Receiver, __completions_t<env_of_t<_Receiver>>> connectexec::__read_with_default::__sender122 static constexpr auto connect(_Self&& __self, _Receiver __rcvr) 123 noexcept(std::is_nothrow_move_constructible_v<_Receiver>) 124 -> __operation_t<_Tag, __default_t<env_of_t<_Receiver>>, _Receiver> { 125 return {{}, static_cast<_Self&&>(__self).__default_, static_cast<_Receiver&&>(__rcvr)}; 126 } 127 128 template <class _Env> get_completion_signaturesexec::__read_with_default::__sender129 constexpr auto get_completion_signatures(_Env&&) -> __completions_t<_Env> { 130 return {}; 131 } 132 }; 133 134 struct __read_with_default_t { 135 template <class _Tag, class _Default> 136 constexpr auto operator ()exec::__read_with_default::__read_with_default_t137 operator()(_Tag, _Default&& __default) const -> __sender<_Tag, __decay_t<_Default>> { 138 return {static_cast<_Default&&>(__default)}; 139 } 140 }; 141 } // namespace __read_with_default 142 143 inline constexpr __read_with_default::__read_with_default_t read_with_default{}; 144 145 [[deprecated("exec::write has been renamed to stdexec::write_env")]] 146 inline constexpr stdexec::__write::write_env_t write{}; 147 [[deprecated("write_env has been moved to the stdexec:: namespace")]] 148 inline constexpr stdexec::__write::write_env_t write_env{}; 149 150 namespace __write_attrs { 151 using namespace stdexec; 152 153 template <class _SenderId, class _Attrs> 154 struct __sender { 155 using _Sender = stdexec::__t<_SenderId>; 156 157 struct __t { 158 using sender_concept = sender_t; 159 using __id = __sender; 160 _Sender __sndr_; 161 _Attrs __attrs_; 162 get_envexec::__write_attrs::__sender::__t163 constexpr auto get_env() const noexcept -> __join_env_t<const _Attrs&, env_of_t<_Sender>> { 164 return stdexec::__env::__join(__attrs_, stdexec::get_env(__sndr_)); 165 } 166 167 template <__decays_to<__t> _Self, class... _Env> get_completion_signaturesexec::__write_attrs::__sender::__t168 static constexpr auto get_completion_signatures(_Self&&, _Env&&...) 169 -> completion_signatures_of_t<__copy_cvref_t<_Self, _Sender>, _Env...> { 170 return {}; 171 } 172 173 template <__decays_to<__t> _Self, class _Receiver> 174 requires sender_in<__copy_cvref_t<_Self, _Sender>, env_of_t<_Receiver>> connectexec::__write_attrs::__sender::__t175 static constexpr auto connect(_Self&& __self, _Receiver __rcvr) 176 -> connect_result_t<__copy_cvref_t<_Self, _Sender>, _Receiver> { 177 return stdexec::connect(std::forward<_Self>(__self).__sndr_, std::move(__rcvr)); 178 } 179 }; 180 }; 181 182 struct __write_attrs_t { 183 template <class _Sender, class _Attrs> STDEXEC_ATTRIBUTEexec::__write_attrs::__write_attrs_t184 STDEXEC_ATTRIBUTE(host, device) 185 constexpr auto 186 operator()(_Sender snd, _Attrs __attrs_) const -> __write_attrs::__sender<_Sender, _Attrs> { 187 return __t<__write_attrs::__sender<__id<_Sender>, _Attrs>>{ 188 static_cast<_Sender&&>(snd), static_cast<_Attrs&&>(__attrs_)}; 189 } 190 191 template <class _Attrs> 192 struct __closure { 193 _Attrs __attrs_; 194 195 template <class _Sender> 196 STDEXEC_ATTRIBUTE(host, device) 197 friend constexpr auto operator|(_Sender __sndr_, __closure _clsr) { 198 return __t<__write_attrs::__sender<__id<_Sender>, _Attrs>>{ 199 static_cast<_Sender&&>(__sndr_), static_cast<_Attrs&&>(_clsr.__attrs_)}; 200 } 201 }; 202 203 template <class _Attrs> STDEXEC_ATTRIBUTEexec::__write_attrs::__write_attrs_t204 STDEXEC_ATTRIBUTE(host, device) 205 constexpr auto operator()(_Attrs __attrs_) const { 206 return __closure<_Attrs>{static_cast<_Attrs&&>(__attrs_)}; 207 } 208 }; 209 } // namespace __write_attrs 210 211 inline constexpr __write_attrs::__write_attrs_t write_attrs{}; 212 213 } // namespace exec 214 215 STDEXEC_PRAGMA_POP() 216