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 "__completion_signatures.hpp" 19 #include "__concepts.hpp" 20 #include "__cpo.hpp" 21 #include "__execution_fwd.hpp" 22 #include "__meta.hpp" 23 #include "__receivers.hpp" 24 #include "__schedulers.hpp" 25 #include "__senders.hpp" 26 #include "__submit.hpp" 27 #include "__tag_invoke.hpp" 28 #include "__transform_sender.hpp" 29 #include "__type_traits.hpp" 30 31 #include <exception> 32 33 namespace stdexec 34 { 35 ///////////////////////////////////////////////////////////////////////////// 36 // [execution.execute] 37 namespace __execute_ 38 { 39 template <class _Fun> 40 struct __as_receiver 41 { 42 using receiver_concept = receiver_t; 43 _Fun __fun_; 44 set_valuestdexec::__execute_::__as_receiver45 void set_value() noexcept 46 { 47 // terminates on exception: 48 __fun_(); 49 } 50 set_errorstdexec::__execute_::__as_receiver51 [[noreturn]] void set_error(std::exception_ptr) noexcept 52 { 53 std::terminate(); 54 } 55 set_stoppedstdexec::__execute_::__as_receiver56 void set_stopped() noexcept {} 57 }; 58 59 struct execute_t 60 { 61 template <scheduler _Scheduler, class _Fun> 62 requires __callable<_Fun&> && move_constructible<_Fun> operator ()stdexec::__execute_::execute_t63 void operator()(_Scheduler&& __sched, _Fun __fun) const noexcept(false) 64 { 65 // Look for a legacy customization 66 if constexpr (tag_invocable<execute_t, _Scheduler, _Fun>) 67 { 68 tag_invoke(execute_t{}, static_cast<_Scheduler&&>(__sched), 69 static_cast<_Fun&&>(__fun)); 70 } 71 else 72 { 73 auto __domain = query_or(get_domain, __sched, default_domain()); 74 stdexec::apply_sender(__domain, *this, 75 schedule(static_cast<_Scheduler&&>(__sched)), 76 static_cast<_Fun&&>(__fun)); 77 } 78 } 79 80 template <sender_of<set_value_t()> _Sender, class _Fun> 81 requires __callable<_Fun&> && move_constructible<_Fun> apply_senderstdexec::__execute_::execute_t82 void apply_sender(_Sender&& __sndr, _Fun __fun) const noexcept(false) 83 { 84 __submit(static_cast<_Sender&&>(__sndr), 85 __as_receiver<_Fun>{static_cast<_Fun&&>(__fun)}); 86 } 87 }; 88 } // namespace __execute_ 89 90 using __execute_::execute_t; 91 inline constexpr execute_t execute{}; 92 } // namespace stdexec 93