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 "__completion_signatures.hpp" 23 #include "__concepts.hpp" 24 #include "__env.hpp" 25 #include "__receivers.hpp" 26 #include "__sender_adaptor_closure.hpp" 27 #include "__senders_core.hpp" 28 #include "__transform_completion_signatures.hpp" 29 #include "__type_traits.hpp" 30 31 #include <exception> 32 #include <optional> 33 34 namespace stdexec 35 { 36 ///////////////////////////////////////////////////////////////////////////// 37 // [execution.senders.adaptors.stopped_as_optional] 38 namespace __sao 39 { 40 struct stopped_as_optional_t 41 { 42 template <sender _Sender> operator ()stdexec::__sao::stopped_as_optional_t43 auto operator()(_Sender&& __sndr) const 44 { 45 return __make_sexpr<stopped_as_optional_t>( 46 __(), static_cast<_Sender&&>(__sndr)); 47 } 48 49 STDEXEC_ATTRIBUTE((always_inline)) operator ()stdexec::__sao::stopped_as_optional_t50 auto operator()() const noexcept -> __binder_back<stopped_as_optional_t> 51 { 52 return {{}, {}, {}}; 53 } 54 }; 55 56 struct __stopped_as_optional_impl : __sexpr_defaults 57 { 58 template <class... _Tys> 59 requires(sizeof...(_Tys) == 1) 60 using __set_value_t = 61 completion_signatures<set_value_t(std::optional<__decay_t<_Tys>>...)>; 62 63 template <class _Ty> 64 using __set_error_t = completion_signatures<set_error_t(_Ty)>; 65 66 static constexpr auto get_completion_signatures = // 67 []<class _Self, class... _Env>(_Self&&, _Env&&...) noexcept // 68 -> transform_completion_signatures< 69 __completion_signatures_of_t<__child_of<_Self>, _Env...>, 70 completion_signatures<set_error_t(std::exception_ptr)>, 71 __set_value_t, __set_error_t, completion_signatures<>> { 72 static_assert(sender_expr_for<_Self, stopped_as_optional_t>); 73 return {}; 74 }; 75 76 static constexpr auto get_state = // 77 []<class _Self, class _Receiver>(_Self&&, _Receiver&) noexcept 78 requires __single_value_sender<__child_of<_Self>, env_of_t<_Receiver>> 79 { 80 static_assert(sender_expr_for<_Self, stopped_as_optional_t>); 81 using _Value = __decay_t< 82 __single_sender_value_t<__child_of<_Self>, env_of_t<_Receiver>>>; 83 return __mtype<_Value>(); 84 }; 85 86 static constexpr auto complete = // 87 []<class _State, class _Receiver, class _Tag, class... _Args>( 88 __ignore, _State&, _Receiver& __rcvr, _Tag, 89 _Args&&... __args) noexcept -> void { 90 if constexpr (__same_as<_Tag, set_value_t>) 91 { 92 try 93 { 94 static_assert(constructible_from<__t<_State>, _Args...>); 95 stdexec::set_value(static_cast<_Receiver&&>(__rcvr), 96 std::optional<__t<_State>>{ 97 static_cast<_Args&&>(__args)...}); 98 } 99 catch (...) 100 { 101 stdexec::set_error(static_cast<_Receiver&&>(__rcvr), 102 std::current_exception()); 103 } 104 } 105 else if constexpr (__same_as<_Tag, set_error_t>) 106 { 107 stdexec::set_error(static_cast<_Receiver&&>(__rcvr), 108 static_cast<_Args&&>(__args)...); 109 } 110 else 111 { 112 stdexec::set_value(static_cast<_Receiver&&>(__rcvr), 113 std::optional<__t<_State>>{std::nullopt}); 114 } 115 }; 116 }; 117 } // namespace __sao 118 119 using __sao::stopped_as_optional_t; 120 inline constexpr stopped_as_optional_t stopped_as_optional{}; 121 122 template <> 123 struct __sexpr_impl<stopped_as_optional_t> : __sao::__stopped_as_optional_impl 124 {}; 125 } // namespace stdexec 126