xref: /openbmc/sdbusplus/include/sdbusplus/async/stdexec/__detail/__schedulers.hpp (revision 10d0b4b7d1498cfd5c3d37edea271a54d1984e41)
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 "__concepts.hpp"
22 #include "__env.hpp"
23 #include "__senders_core.hpp"
24 #include "__tag_invoke.hpp"
25 
26 namespace stdexec {
27   /////////////////////////////////////////////////////////////////////////////
28   // [execution.senders.schedule]
29   namespace __sched {
30     template <class _Scheduler>
31     concept __has_schedule_member = requires(_Scheduler&& __sched) {
32       static_cast<_Scheduler &&>(__sched).schedule();
33     };
34 
35     struct schedule_t {
36       template <class _Scheduler>
37         requires __has_schedule_member<_Scheduler>
STDEXEC_ATTRIBUTEstdexec::__sched::schedule_t38       STDEXEC_ATTRIBUTE(host, device, always_inline)
39       auto operator()(_Scheduler&& __sched) const
40         noexcept(noexcept(static_cast<_Scheduler&&>(__sched).schedule()))
41           -> decltype(static_cast<_Scheduler&&>(__sched).schedule()) {
42         static_assert(
43           sender<decltype(static_cast<_Scheduler&&>(__sched).schedule())>,
44           "schedule() member functions must return a sender");
45         return static_cast<_Scheduler&&>(__sched).schedule();
46       }
47 
48       template <class _Scheduler>
49         requires(!__has_schedule_member<_Scheduler>) && tag_invocable<schedule_t, _Scheduler>
STDEXEC_ATTRIBUTEstdexec::__sched::schedule_t50       STDEXEC_ATTRIBUTE(host, device, always_inline)
51       auto operator()(_Scheduler&& __sched) const
52         noexcept(nothrow_tag_invocable<schedule_t, _Scheduler>)
53           -> tag_invoke_result_t<schedule_t, _Scheduler> {
54         static_assert(sender<tag_invoke_result_t<schedule_t, _Scheduler>>);
55         return tag_invoke(*this, static_cast<_Scheduler&&>(__sched));
56       }
57 
querystdexec::__sched::schedule_t58       static constexpr auto query(forwarding_query_t) noexcept -> bool {
59         return false;
60       }
61     };
62   } // namespace __sched
63 
64   using __sched::schedule_t;
65   inline constexpr schedule_t schedule{};
66 
67   struct scheduler_t { };
68 
69   template <class _Scheduler>
70   concept __has_schedule = requires(_Scheduler&& __sched) {
71     { schedule(static_cast<_Scheduler &&>(__sched)) } -> sender;
72   };
73 
74   template <class _Scheduler>
75   concept __sender_has_completion_scheduler = requires(_Scheduler&& __sched) {
76     {
77       stdexec::__decay_copy(
78         get_completion_scheduler<set_value_t>(
79           get_env(schedule(static_cast<_Scheduler &&>(__sched)))))
80     } -> same_as<__decay_t<_Scheduler>>;
81   };
82 
83   template <class _Scheduler>
84   concept scheduler = __has_schedule<_Scheduler> && __sender_has_completion_scheduler<_Scheduler>
85                    && equality_comparable<__decay_t<_Scheduler>>
86                    && copy_constructible<__decay_t<_Scheduler>>;
87 
88   template <scheduler _Scheduler>
89   using schedule_result_t = __call_result_t<schedule_t, _Scheduler>;
90 
91   template <class _SchedulerProvider>
92   concept __scheduler_provider = requires(const _SchedulerProvider& __sp) {
93     { get_scheduler(__sp) } -> scheduler;
94   };
95 
96   namespace __queries {
97     template <class _Env>
STDEXEC_ATTRIBUTE(always_inline,host,device)98     STDEXEC_ATTRIBUTE(always_inline, host, device)
99     constexpr void get_scheduler_t::__validate() noexcept {
100       static_assert(__nothrow_callable<get_scheduler_t, const _Env&>);
101       static_assert(scheduler<__call_result_t<get_scheduler_t, const _Env&>>);
102     }
103 
104     template <class _Env>
STDEXEC_ATTRIBUTE(always_inline,host,device)105     STDEXEC_ATTRIBUTE(always_inline, host, device)
106     constexpr void get_delegation_scheduler_t::__validate() noexcept {
107       static_assert(__nothrow_callable<get_delegation_scheduler_t, const _Env&>);
108       static_assert(scheduler<__call_result_t<get_delegation_scheduler_t, const _Env&>>);
109     }
110 
111     template <__completion_tag _Tag>
112     template <class _Env>
STDEXEC_ATTRIBUTE(always_inline,host,device)113     STDEXEC_ATTRIBUTE(always_inline, host, device)
114     constexpr void get_completion_scheduler_t<_Tag>::__validate() noexcept {
115       static_assert(__nothrow_callable<get_completion_scheduler_t<_Tag>, const _Env&>);
116       static_assert(scheduler<__call_result_t<get_completion_scheduler_t<_Tag>, const _Env&>>);
117     }
118   } // namespace __queries
119 } // namespace stdexec
120