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 "__env.hpp" 24 #include "__meta.hpp" 25 #include "__schedule_from.hpp" 26 #include "__schedulers.hpp" 27 #include "__sender_adaptor_closure.hpp" 28 #include "__sender_introspection.hpp" 29 #include "__senders.hpp" 30 #include "__tag_invoke.hpp" 31 #include "__transform_sender.hpp" 32 #include "__type_traits.hpp" 33 34 #include <utility> 35 36 namespace stdexec 37 { 38 ///////////////////////////////////////////////////////////////////////////// 39 // [execution.senders.adaptors.continue_on] 40 namespace __continue_on 41 { 42 using __schfr::__environ; 43 44 template <class _Env> 45 using __scheduler_t = __result_of<get_completion_scheduler<set_value_t>, _Env>; 46 47 template <class _Sender> 48 using __lowered_t = // 49 __result_of<schedule_from, __scheduler_t<__data_of<_Sender>>, 50 __child_of<_Sender>>; 51 52 struct continue_on_t 53 { 54 template <sender _Sender, scheduler _Scheduler> operator ()stdexec::__continue_on::continue_on_t55 auto operator()(_Sender&& __sndr, 56 _Scheduler&& __sched) const -> __well_formed_sender auto 57 { 58 auto __domain = __get_early_domain(__sndr); 59 using _Env = __t<__environ<__id<__decay_t<_Scheduler>>>>; 60 return stdexec::transform_sender( 61 __domain, __make_sexpr<continue_on_t>( 62 _Env{{static_cast<_Scheduler&&>(__sched)}}, 63 static_cast<_Sender&&>(__sndr))); 64 } 65 66 template <scheduler _Scheduler> 67 STDEXEC_ATTRIBUTE((always_inline)) operator ()stdexec::__continue_on::continue_on_t68 auto operator()(_Scheduler&& __sched) const 69 -> __binder_back<continue_on_t, __decay_t<_Scheduler>> 70 { 71 return {{static_cast<_Scheduler&&>(__sched)}, {}, {}}; 72 } 73 74 ////////////////////////////////////////////////////////////////////////////////////////////// 75 using _Env = __0; 76 using _Sender = __1; 77 using __legacy_customizations_t = // 78 __types<tag_invoke_t(continue_on_t, 79 get_completion_scheduler_t<set_value_t>( 80 get_env_t(const _Sender&)), 81 _Sender, 82 get_completion_scheduler_t<set_value_t>(_Env)), 83 tag_invoke_t(continue_on_t, _Sender, 84 get_completion_scheduler_t<set_value_t>(_Env))>; 85 86 template <class _Env> __transform_sender_fnstdexec::__continue_on::continue_on_t87 static auto __transform_sender_fn(const _Env&) 88 { 89 return [&]<class _Data, class _Child>(__ignore, _Data&& __data, 90 _Child&& __child) { 91 auto __sched = get_completion_scheduler<set_value_t>(__data); 92 return schedule_from(std::move(__sched), 93 static_cast<_Child&&>(__child)); 94 }; 95 } 96 97 template <class _Sender, class _Env> transform_senderstdexec::__continue_on::continue_on_t98 static auto transform_sender(_Sender&& __sndr, const _Env& __env) 99 { 100 return __sexpr_apply(static_cast<_Sender&&>(__sndr), 101 __transform_sender_fn(__env)); 102 } 103 }; 104 105 struct __continue_on_impl : __sexpr_defaults 106 { 107 static constexpr auto get_attrs = // 108 []<class _Data, class _Child>( 109 const _Data& __data, 110 const _Child& __child) noexcept -> decltype(auto) { 111 return __env::__join(__data, stdexec::get_env(__child)); 112 }; 113 114 static constexpr auto get_completion_signatures = // 115 []<class _Sender>(_Sender&&) noexcept // 116 -> __completion_signatures_of_t< // 117 transform_sender_result_t<default_domain, _Sender, empty_env>> {}; 118 }; 119 } // namespace __continue_on 120 121 using __continue_on::continue_on_t; 122 inline constexpr continue_on_t continue_on{}; 123 124 using transfer_t = continue_on_t; 125 inline constexpr transfer_t transfer{}; 126 127 template <> 128 struct __sexpr_impl<continue_on_t> : __continue_on::__continue_on_impl 129 {}; 130 } // namespace stdexec 131