xref: /openbmc/sdbusplus/include/sdbusplus/async/stdexec/__detail/__execute.hpp (revision 5cee91570368554a7fcbbd9418f65efda449fa70)
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