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 "__meta.hpp" 24 #include "__sender_adaptor_closure.hpp" 25 #include "__senders.hpp" 26 #include "__shared.hpp" 27 #include "__transform_sender.hpp" 28 #include "__type_traits.hpp" 29 30 namespace stdexec { 31 //////////////////////////////////////////////////////////////////////////// 32 // [execution.senders.adaptors.split] 33 namespace __split { 34 using namespace __shared; 35 36 struct __split_t { }; 37 38 struct split_t { 39 template <sender _Sender, class _Env = env<>> 40 requires sender_in<_Sender, _Env> && __decay_copyable<env_of_t<_Sender>> operator ()stdexec::__split::split_t41 auto operator()(_Sender&& __sndr, _Env&& __env = {}) const -> __well_formed_sender auto { 42 auto __domain = __get_late_domain(__sndr, __env, __get_early_domain(__sndr)); 43 return stdexec::transform_sender( 44 __domain, 45 __make_sexpr<split_t>(static_cast<_Env&&>(__env), static_cast<_Sender&&>(__sndr))); 46 } 47 STDEXEC_ATTRIBUTEstdexec::__split::split_t48 STDEXEC_ATTRIBUTE(always_inline) 49 auto operator()() const noexcept -> __binder_back<split_t> { 50 return {{}, {}, {}}; 51 } 52 53 template <class _CvrefSender, class _Env> 54 using __receiver_t = __t<__meval<__receiver, __cvref_id<_CvrefSender>, __id<_Env>>>; 55 56 template <class _Sender> transform_senderstdexec::__split::split_t57 static auto transform_sender(_Sender&& __sndr) { 58 using _Receiver = __receiver_t<__child_of<_Sender>, __decay_t<__data_of<_Sender>>>; 59 static_assert(sender_to<__child_of<_Sender>, _Receiver>); 60 61 return __sexpr_apply( 62 static_cast<_Sender&&>(__sndr), 63 [&]<class _Env, class _Child>(__ignore, _Env&& __env, _Child&& __child) { 64 // The shared state starts life with a ref-count of one. 65 auto* __sh_state = 66 new __shared_state{static_cast<_Child&&>(__child), static_cast<_Env&&>(__env)}; 67 68 return __make_sexpr<__split_t>(__box{__split_t(), __sh_state}); 69 }); 70 } 71 }; 72 } // namespace __split 73 74 using __split::split_t; 75 inline constexpr split_t split{}; 76 77 template <> 78 struct __sexpr_impl<__split::__split_t> : __shared::__shared_impl<__split::__split_t> { }; 79 80 template <> 81 struct __sexpr_impl<split_t> : __sexpr_defaults { 82 static constexpr auto get_completion_signatures = []<class _Sender>(_Sender&&) noexcept 83 -> __completion_signatures_of_t<transform_sender_result_t<default_domain, _Sender, env<>>> { 84 }; 85 }; 86 } // namespace stdexec 87