1 // 2 // execution/execute.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef BOOST_ASIO_EXECUTION_EXECUTE_HPP 12 #define BOOST_ASIO_EXECUTION_EXECUTE_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <boost/asio/detail/config.hpp> 19 #include <boost/asio/detail/type_traits.hpp> 20 #include <boost/asio/execution/detail/as_invocable.hpp> 21 #include <boost/asio/execution/detail/as_receiver.hpp> 22 #include <boost/asio/traits/execute_member.hpp> 23 #include <boost/asio/traits/execute_free.hpp> 24 25 #include <boost/asio/detail/push_options.hpp> 26 27 #if defined(GENERATING_DOCUMENTATION) 28 29 namespace boost { 30 namespace asio { 31 namespace execution { 32 33 /// A customisation point that executes a function on an executor. 34 /** 35 * The name <tt>execution::execute</tt> denotes a customisation point object. 36 * 37 * For some subexpressions <tt>e</tt> and <tt>f</tt>, let <tt>E</tt> be a type 38 * such that <tt>decltype((e))</tt> is <tt>E</tt> and let <tt>F</tt> be a type 39 * such that <tt>decltype((f))</tt> is <tt>F</tt>. The expression 40 * <tt>execution::execute(e, f)</tt> is ill-formed if <tt>F</tt> does not model 41 * <tt>invocable</tt>, or if <tt>E</tt> does not model either <tt>executor</tt> 42 * or <tt>sender</tt>. Otherwise, it is expression-equivalent to: 43 * 44 * @li <tt>e.execute(f)</tt>, if that expression is valid. If the function 45 * selected does not execute the function object <tt>f</tt> on the executor 46 * <tt>e</tt>, the program is ill-formed with no diagnostic required. 47 * 48 * @li Otherwise, <tt>execute(e, f)</tt>, if that expression is valid, with 49 * overload resolution performed in a context that includes the declaration 50 * <tt>void execute();</tt> and that does not include a declaration of 51 * <tt>execution::execute</tt>. If the function selected by overload 52 * resolution does not execute the function object <tt>f</tt> on the executor 53 * <tt>e</tt>, the program is ill-formed with no diagnostic required. 54 */ 55 inline constexpr unspecified execute = unspecified; 56 57 /// A type trait that determines whether a @c execute expression is well-formed. 58 /** 59 * Class template @c can_execute is a trait that is derived from 60 * @c true_type if the expression <tt>execution::execute(std::declval<T>(), 61 * std::declval<F>())</tt> is well formed; otherwise @c false_type. 62 */ 63 template <typename T, typename F> 64 struct can_execute : 65 integral_constant<bool, automatically_determined> 66 { 67 }; 68 69 } // namespace execution 70 } // namespace asio 71 } // namespace boost 72 73 #else // defined(GENERATING_DOCUMENTATION) 74 75 namespace boost { 76 namespace asio { 77 namespace execution { 78 79 template <typename T, typename R> 80 struct is_sender_to; 81 82 namespace detail { 83 84 template <typename S, typename R> 85 void submit_helper(BOOST_ASIO_MOVE_ARG(S) s, BOOST_ASIO_MOVE_ARG(R) r); 86 87 } // namespace detail 88 } // namespace execution 89 } // namespace asio 90 } // namespace boost 91 namespace asio_execution_execute_fn { 92 93 using boost::asio::conditional; 94 using boost::asio::decay; 95 using boost::asio::declval; 96 using boost::asio::enable_if; 97 using boost::asio::execution::detail::as_receiver; 98 using boost::asio::execution::detail::is_as_invocable; 99 using boost::asio::execution::is_sender_to; 100 using boost::asio::false_type; 101 using boost::asio::result_of; 102 using boost::asio::traits::execute_free; 103 using boost::asio::traits::execute_member; 104 using boost::asio::true_type; 105 106 void execute(); 107 108 enum overload_type 109 { 110 call_member, 111 call_free, 112 adapter, 113 ill_formed 114 }; 115 116 template <typename T, typename F, typename = void> 117 struct call_traits 118 { 119 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); 120 }; 121 122 template <typename T, typename F> 123 struct call_traits<T, void(F), 124 typename enable_if< 125 ( 126 execute_member<T, F>::is_valid 127 ) 128 >::type> : 129 execute_member<T, F> 130 { 131 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); 132 }; 133 134 template <typename T, typename F> 135 struct call_traits<T, void(F), 136 typename enable_if< 137 ( 138 !execute_member<T, F>::is_valid 139 && 140 execute_free<T, F>::is_valid 141 ) 142 >::type> : 143 execute_free<T, F> 144 { 145 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); 146 }; 147 148 template <typename T, typename F> 149 struct call_traits<T, void(F), 150 typename enable_if< 151 ( 152 !execute_member<T, F>::is_valid 153 && 154 !execute_free<T, F>::is_valid 155 && 156 conditional<true, true_type, 157 typename result_of<typename decay<F>::type&()>::type 158 >::type::value 159 && 160 conditional< 161 !is_as_invocable< 162 typename decay<F>::type 163 >::value, 164 is_sender_to< 165 T, 166 as_receiver<typename decay<F>::type, T> 167 >, 168 false_type 169 >::type::value 170 ) 171 >::type> 172 { 173 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter); 174 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 175 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 176 typedef void result_type; 177 }; 178 179 struct impl 180 { 181 template <typename T, typename F> 182 BOOST_ASIO_CONSTEXPR typename enable_if< 183 call_traits<T, void(F)>::overload == call_member, 184 typename call_traits<T, void(F)>::result_type 185 >::type operator ()asio_execution_execute_fn::impl186 operator()( 187 BOOST_ASIO_MOVE_ARG(T) t, 188 BOOST_ASIO_MOVE_ARG(F) f) const 189 BOOST_ASIO_NOEXCEPT_IF(( 190 call_traits<T, void(F)>::is_noexcept)) 191 { 192 return BOOST_ASIO_MOVE_CAST(T)(t).execute(BOOST_ASIO_MOVE_CAST(F)(f)); 193 } 194 195 template <typename T, typename F> 196 BOOST_ASIO_CONSTEXPR typename enable_if< 197 call_traits<T, void(F)>::overload == call_free, 198 typename call_traits<T, void(F)>::result_type 199 >::type operator ()asio_execution_execute_fn::impl200 operator()( 201 BOOST_ASIO_MOVE_ARG(T) t, 202 BOOST_ASIO_MOVE_ARG(F) f) const 203 BOOST_ASIO_NOEXCEPT_IF(( 204 call_traits<T, void(F)>::is_noexcept)) 205 { 206 return execute(BOOST_ASIO_MOVE_CAST(T)(t), BOOST_ASIO_MOVE_CAST(F)(f)); 207 } 208 209 template <typename T, typename F> 210 BOOST_ASIO_CONSTEXPR typename enable_if< 211 call_traits<T, void(F)>::overload == adapter, 212 typename call_traits<T, void(F)>::result_type 213 >::type operator ()asio_execution_execute_fn::impl214 operator()( 215 BOOST_ASIO_MOVE_ARG(T) t, 216 BOOST_ASIO_MOVE_ARG(F) f) const 217 BOOST_ASIO_NOEXCEPT_IF(( 218 call_traits<T, void(F)>::is_noexcept)) 219 { 220 return boost::asio::execution::detail::submit_helper( 221 BOOST_ASIO_MOVE_CAST(T)(t), 222 as_receiver<typename decay<F>::type, T>( 223 BOOST_ASIO_MOVE_CAST(F)(f), 0)); 224 } 225 }; 226 227 template <typename T = impl> 228 struct static_instance 229 { 230 static const T instance; 231 }; 232 233 template <typename T> 234 const T static_instance<T>::instance = {}; 235 236 } // namespace asio_execution_execute_fn 237 namespace boost { 238 namespace asio { 239 namespace execution { 240 namespace { 241 242 static BOOST_ASIO_CONSTEXPR const asio_execution_execute_fn::impl& 243 execute = asio_execution_execute_fn::static_instance<>::instance; 244 245 } // namespace 246 247 template <typename T, typename F> 248 struct can_execute : 249 integral_constant<bool, 250 asio_execution_execute_fn::call_traits<T, void(F)>::overload != 251 asio_execution_execute_fn::ill_formed> 252 { 253 }; 254 255 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 256 257 template <typename T, typename F> 258 constexpr bool can_execute_v = can_execute<T, F>::value; 259 260 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 261 262 } // namespace execution 263 } // namespace asio 264 } // namespace boost 265 266 #endif // defined(GENERATING_DOCUMENTATION) 267 268 #include <boost/asio/detail/pop_options.hpp> 269 270 #endif // BOOST_ASIO_EXECUTION_EXECUTE_HPP 271