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 "__cpo.hpp" 19 #include "__env.hpp" 20 #include "__execution_fwd.hpp" 21 #include "__meta.hpp" 22 #include "__receivers.hpp" 23 #include "__senders.hpp" 24 #include "__submit.hpp" 25 #include "__transform_sender.hpp" 26 #include "__type_traits.hpp" 27 28 namespace stdexec 29 { 30 ///////////////////////////////////////////////////////////////////////////// 31 // [execution.senders.consumer.start_detached] 32 namespace __start_detached 33 { 34 template <class _EnvId> 35 struct __detached_receiver 36 { 37 using _Env = stdexec::__t<_EnvId>; 38 39 struct __t 40 { 41 using receiver_concept = receiver_t; 42 using __id = __detached_receiver; 43 STDEXEC_ATTRIBUTE((no_unique_address)) 44 _Env __env_; 45 46 template <class... _As> set_valuestdexec::__start_detached::__detached_receiver::__t47 void set_value(_As&&...) noexcept 48 {} 49 50 template <class _Error> set_errorstdexec::__start_detached::__detached_receiver::__t51 [[noreturn]] void set_error(_Error&&) noexcept 52 { 53 std::terminate(); 54 } 55 set_stoppedstdexec::__start_detached::__detached_receiver::__t56 void set_stopped() noexcept {} 57 get_envstdexec::__start_detached::__detached_receiver::__t58 auto get_env() const noexcept -> const _Env& 59 { 60 // BUGBUG NOT TO SPEC 61 return __env_; 62 } 63 }; 64 }; 65 66 template <class _Env = empty_env> 67 using __detached_receiver_t = __t<__detached_receiver<__id<__decay_t<_Env>>>>; 68 69 struct start_detached_t 70 { 71 template <sender_in<__root_env> _Sender> 72 requires __callable<apply_sender_t, __early_domain_of_t<_Sender>, 73 start_detached_t, _Sender> operator ()stdexec::__start_detached::start_detached_t74 void operator()(_Sender&& __sndr) const 75 { 76 auto __domain = __get_early_domain(__sndr); 77 stdexec::apply_sender(__domain, *this, static_cast<_Sender&&>(__sndr)); 78 } 79 80 template <class _Env, sender_in<__as_root_env_t<_Env>> _Sender> 81 requires __callable<apply_sender_t, 82 __late_domain_of_t<_Sender, __as_root_env_t<_Env>>, 83 start_detached_t, _Sender, __as_root_env_t<_Env>> operator ()stdexec::__start_detached::start_detached_t84 void operator()(_Sender&& __sndr, _Env&& __env) const 85 { 86 auto __domain = __get_late_domain(__sndr, __env); 87 stdexec::apply_sender(__domain, *this, static_cast<_Sender&&>(__sndr), 88 __as_root_env(static_cast<_Env&&>(__env))); 89 } 90 91 using _Sender = __0; 92 using __legacy_customizations_t = 93 __types<tag_invoke_t(start_detached_t, 94 get_completion_scheduler_t<set_value_t>( 95 get_env_t(const _Sender&)), 96 _Sender), 97 tag_invoke_t(start_detached_t, _Sender)>; 98 99 template <class _Sender, class _Env = __root_env> 100 requires sender_to<_Sender, __detached_receiver_t<_Env>> apply_senderstdexec::__start_detached::start_detached_t101 void apply_sender(_Sender&& __sndr, _Env&& __env = {}) const 102 { 103 __submit(static_cast<_Sender&&>(__sndr), 104 __detached_receiver_t<_Env>{static_cast<_Env&&>(__env)}); 105 } 106 }; 107 } // namespace __start_detached 108 109 using __start_detached::start_detached_t; 110 inline constexpr start_detached_t start_detached{}; 111 } // namespace stdexec 112