xref: /openbmc/sdbusplus/include/sdbusplus/async/stdexec/__detail/__sender_introspection.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 namespace stdexec {
21   namespace __detail {
22     // Accessor for the "data" field of a sender
23     struct __get_data {
24       template <class _Data>
STDEXEC_ATTRIBUTEstdexec::__detail::__get_data25       STDEXEC_ATTRIBUTE(always_inline)
26       auto operator()(__ignore, _Data&& __data, auto&&...) const noexcept -> _Data&& {
27         return static_cast<_Data&&>(__data);
28       }
29     };
30 
31     // A function object that is to senders what std::apply is to tuples:
32     struct __sexpr_apply_t {
33       template <class _Sender, class _ApplyFn>
STDEXEC_ATTRIBUTEstdexec::__detail::__sexpr_apply_t34       STDEXEC_ATTRIBUTE(always_inline)
35       auto operator()(_Sender&& __sndr, _ApplyFn&& __fun) const
36         noexcept(noexcept(__sndr
37                             .apply(static_cast<_Sender&&>(__sndr), static_cast<_ApplyFn&&>(__fun))))
38           -> decltype(__sndr
39                         .apply(static_cast<_Sender&&>(__sndr), static_cast<_ApplyFn&&>(__fun))) {
40         return __sndr.apply(static_cast<_Sender&&>(__sndr), static_cast<_ApplyFn&&>(__fun));
41       }
42     };
43 
44     // A type that describes a sender's metadata
45     template <class _Tag, class _Data, class... _Child>
46     struct __desc {
47       using __tag = _Tag;
48       using __data = _Data;
49       using __children = __types<_Child...>;
50 
51       template <class _Fn>
52       using __f = __minvoke<_Fn, _Tag, _Data, _Child...>;
53     };
54 
55     template <class _Fn>
56     struct __sexpr_uncurry_fn {
57       template <class _Tag, class _Data, class... _Child>
58       constexpr auto operator()(_Tag, _Data&&, _Child&&...) const noexcept
59         -> __minvoke<_Fn, _Tag, _Data, _Child...>;
60     };
61 
62     template <class _CvrefSender, class _Fn>
63     using __sexpr_uncurry = __call_result_t<__sexpr_apply_t, _CvrefSender, __sexpr_uncurry_fn<_Fn>>;
64 
65     template <class _Sender>
66     using __desc_of = __sexpr_uncurry<_Sender, __q<__desc>>;
67 
68     using __get_desc = __sexpr_uncurry_fn<__q<__desc>>;
69   } // namespace __detail
70 
71   using __detail::__sexpr_apply_t;
72   inline constexpr __sexpr_apply_t __sexpr_apply{};
73 
74   template <class _Sender, class _ApplyFn>
75   using __sexpr_apply_result_t = __call_result_t<__sexpr_apply_t, _Sender, _ApplyFn>;
76 
77   template <class _Sender>
78   using tag_of_t = __detail::__desc_of<_Sender>::__tag;
79 
80   template <class _Sender>
81   using __data_of = __detail::__desc_of<_Sender>::__data;
82 
83   template <class _Sender, class _Continuation = __q<__types>>
84   using __children_of = __mapply<_Continuation, typename __detail::__desc_of<_Sender>::__children>;
85 
86   template <class _Ny, class _Sender>
87   using __nth_child_of = __children_of<_Sender, __mbind_front_q<__m_at, _Ny>>;
88 
89   template <std::size_t _Ny, class _Sender>
90   using __nth_child_of_c = __children_of<_Sender, __mbind_front_q<__m_at, __msize_t<_Ny>>>;
91 
92   template <class _Sender>
93   using __child_of = __children_of<_Sender, __q<__mfront>>;
94 
95   template <class _Sender>
96   inline constexpr std::size_t __nbr_children_of = __v<__children_of<_Sender, __msize>>;
97 
98   template <class _Tp>
99     requires __mvalid<tag_of_t, _Tp>
100   struct __muncurry_<_Tp> {
101     template <class _Fn>
102     using __f = __detail::__sexpr_uncurry<_Tp, _Fn>;
103   };
104 
105   template <class _Sender>
106   concept sender_expr = __mvalid<tag_of_t, _Sender>;
107 
108   template <class _Sender, class _Tag>
109   concept sender_expr_for = sender_expr<_Sender> && same_as<tag_of_t<_Sender>, _Tag>;
110 } // namespace stdexec
111