1 /* 2 * Copyright (c) 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 "__config.hpp" 19 #include "__execution_fwd.hpp" 20 21 /////////////////////////////////////////////////////////////////////////////// 22 /// To hook a customization point like stdexec::get_env, first bring the names 23 /// in stdexec::tags into scope: 24 /// 25 /// @code 26 /// using namespace stdexec::tags; 27 /// @endcode 28 /// 29 /// Then define a member function like this: 30 /// 31 /// @code 32 /// STDEXEC_MEMFN_DECL(auto get_env)(this const MySender& self) { 33 /// return ...; 34 /// } 35 /// @endcode 36 #define STDEXEC_MEMFN_DECL(...) \ 37 friend STDEXEC_EVAL(STDEXEC_MEMFN_DECL_TAG_INVOKE, \ 38 STDEXEC_MEMFN_DECL_WHICH(__VA_ARGS__), __VA_ARGS__) 39 40 #define STDEXEC_MEMFN_DECL_WHICH(_A1, ...) \ 41 STDEXEC_CAT(STDEXEC_MEMFN_DECL_WHICH_, STDEXEC_FRONT(__VA_OPT__(1, ) 0)) \ 42 (_A1, __VA_ARGS__) 43 #define STDEXEC_MEMFN_DECL_WHICH_0(_A1, ...) \ 44 STDEXEC_CHECK(STDEXEC_MEMFN_DECL_PROBE_##_A1), \ 45 STDEXEC_CHECK(_A1##_STDEXEC_MEMFN_DECL_PROBE) 46 #define STDEXEC_MEMFN_DECL_WHICH_1(_A1, ...) \ 47 0, STDEXEC_CHECK( \ 48 STDEXEC_CAT(STDEXEC_BACK(__VA_ARGS__), _STDEXEC_MEMFN_DECL_PROBE)) 49 50 #define STDEXEC_MEMFN_DECL_TAG_INVOKE(_WHICH, _QUERY, ...) \ 51 STDEXEC_MEMFN_DECL_RETURN_ ## _WHICH(__VA_ARGS__) \ 52 tag_invoke(STDEXEC_MEMFN_DECL_TAG_ ## _WHICH ## _QUERY(__VA_ARGS__) 53 54 #define STDEXEC_MEMFN_DECL_ARGS(...) \ 55 STDEXEC_CAT(STDEXEC_EAT_THIS_, __VA_ARGS__)) 56 57 #define STDEXEC_MEMFN_DECL_QUERY(_SELF, _TAG, ...) \ 58 _TAG, STDEXEC_CAT(STDEXEC_EAT_THIS_, _SELF) __VA_OPT__(, __VA_ARGS__)) 59 60 #define STDEXEC_EAT_THIS_this 61 #define STDEXEC_EAT_AUTO_auto 62 #define STDEXEC_EAT_VOID_void 63 64 #define query_STDEXEC_MEMFN_DECL_PROBE STDEXEC_PROBE(~, 1) 65 #define STDEXEC_MEMFN_DECL_PROBE_auto STDEXEC_PROBE(~, 1) 66 #define STDEXEC_MEMFN_DECL_PROBE_void STDEXEC_PROBE(~, 2) 67 68 #define STDEXEC_MEMFN_DECL_RETURN_0(...) \ 69 ::stdexec::__arg_type_t<void(__VA_ARGS__())> 70 #define STDEXEC_MEMFN_DECL_RETURN_1(...) auto 71 #define STDEXEC_MEMFN_DECL_RETURN_2(...) void 72 73 #define STDEXEC_MEMFN_DECL_TAG_00(...) \ 74 const ::stdexec::__tag_type_t<__VA_ARGS__##_t::*>&, STDEXEC_MEMFN_DECL_ARGS 75 #define STDEXEC_MEMFN_DECL_TAG_10(...) \ 76 const STDEXEC_EAT_AUTO_##__VA_ARGS__##_t&, STDEXEC_MEMFN_DECL_ARGS 77 #define STDEXEC_MEMFN_DECL_TAG_20(...) \ 78 const STDEXEC_EAT_VOID_##__VA_ARGS__##_t&, STDEXEC_MEMFN_DECL_ARGS 79 #define STDEXEC_MEMFN_DECL_TAG_01(...) STDEXEC_MEMFN_DECL_QUERY 80 #define STDEXEC_MEMFN_DECL_TAG_11(...) STDEXEC_MEMFN_DECL_QUERY 81 #define STDEXEC_MEMFN_DECL_TAG_21(...) STDEXEC_MEMFN_DECL_QUERY 82 83 #define STDEXEC_MEMFN_FRIEND(_TAG) \ 84 using STDEXEC_CAT(_TAG, _t) = STDEXEC_CAT(stdexec::_TAG, _t) 85 86 #if STDEXEC_MSVC() 87 #pragma deprecated(STDEXEC_CUSTOM) 88 #endif 89 90 #if STDEXEC_GCC() || (STDEXEC_CLANG() && __clang_major__ < 14) 91 #define STDEXEC_CUSTOM \ 92 _Pragma( \ 93 "GCC warning \"STDEXEC_CUSTOM is deprecated; use STDEXEC_MEMFN_DECL instead.\"") \ 94 STDEXEC_MEMFN_DECL 95 #else 96 #define STDEXEC_CUSTOM STDEXEC_MEMFN_DECL 97 #endif 98 99 #if STDEXEC_CLANG() && __clang_major__ >= 14 100 #pragma clang deprecated(STDEXEC_CUSTOM, "use STDEXEC_MEMFN_DECL instead.") 101 #endif 102 103 namespace stdexec 104 { 105 template <class> 106 struct __arg_type; 107 108 template <class _Arg> 109 struct __arg_type<void(_Arg (*)())> 110 { 111 using type = _Arg; 112 }; 113 114 template <class _Fn> 115 using __arg_type_t = typename __arg_type<_Fn>::type; 116 117 template <class> 118 struct __tag_type; 119 120 template <class _Ret, class _Tag> 121 struct __tag_type<_Ret _Tag::*> 122 { 123 using type = _Tag; 124 }; 125 126 template <class _Fn> 127 using __tag_type_t = typename __tag_type<_Fn>::type; 128 129 namespace tags 130 { 131 using stdexec::connect_t; 132 using stdexec::get_completion_signatures_t; 133 using stdexec::get_env_t; 134 using stdexec::set_error_t; 135 using stdexec::set_stopped_t; 136 using stdexec::set_value_t; 137 using stdexec::start_t; 138 } // namespace tags 139 } // namespace stdexec 140