1 // 2 // execution/schedule.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_SCHEDULE_HPP 12 #define BOOST_ASIO_EXECUTION_SCHEDULE_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/executor.hpp> 21 #include <boost/asio/traits/schedule_member.hpp> 22 #include <boost/asio/traits/schedule_free.hpp> 23 24 #include <boost/asio/detail/push_options.hpp> 25 26 #if defined(GENERATING_DOCUMENTATION) 27 28 namespace boost { 29 namespace asio { 30 namespace execution { 31 32 /// A customisation point that is used to obtain a sender from a scheduler. 33 /** 34 * The name <tt>execution::schedule</tt> denotes a customisation point object. 35 * For some subexpression <tt>s</tt>, let <tt>S</tt> be a type such that 36 * <tt>decltype((s))</tt> is <tt>S</tt>. The expression 37 * <tt>execution::schedule(s)</tt> is expression-equivalent to: 38 * 39 * @li <tt>s.schedule()</tt>, if that expression is valid and its type models 40 * <tt>sender</tt>. 41 * 42 * @li Otherwise, <tt>schedule(s)</tt>, if that expression is valid and its 43 * type models <tt>sender</tt> with overload resolution performed in a context 44 * that includes the declaration <tt>void schedule();</tt> and that does not 45 * include a declaration of <tt>execution::schedule</tt>. 46 * 47 * @li Otherwise, <tt>S</tt> if <tt>S</tt> satisfies <tt>executor</tt>. 48 * 49 * @li Otherwise, <tt>execution::schedule(s)</tt> is ill-formed. 50 */ 51 inline constexpr unspecified schedule = unspecified; 52 53 /// A type trait that determines whether a @c schedule expression is 54 /// well-formed. 55 /** 56 * Class template @c can_schedule is a trait that is derived from @c true_type 57 * if the expression <tt>execution::schedule(std::declval<S>())</tt> is well 58 * formed; otherwise @c false_type. 59 */ 60 template <typename S> 61 struct can_schedule : 62 integral_constant<bool, automatically_determined> 63 { 64 }; 65 66 } // namespace execution 67 } // namespace asio 68 } // namespace boost 69 70 #else // defined(GENERATING_DOCUMENTATION) 71 72 namespace asio_execution_schedule_fn { 73 74 using boost::asio::decay; 75 using boost::asio::declval; 76 using boost::asio::enable_if; 77 using boost::asio::execution::is_executor; 78 using boost::asio::traits::schedule_free; 79 using boost::asio::traits::schedule_member; 80 81 void schedule(); 82 83 enum overload_type 84 { 85 identity, 86 call_member, 87 call_free, 88 ill_formed 89 }; 90 91 template <typename S, typename = void> 92 struct call_traits 93 { 94 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); 95 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 96 typedef void result_type; 97 }; 98 99 template <typename S> 100 struct call_traits<S, 101 typename enable_if< 102 ( 103 schedule_member<S>::is_valid 104 ) 105 >::type> : 106 schedule_member<S> 107 { 108 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); 109 }; 110 111 template <typename S> 112 struct call_traits<S, 113 typename enable_if< 114 ( 115 !schedule_member<S>::is_valid 116 && 117 schedule_free<S>::is_valid 118 ) 119 >::type> : 120 schedule_free<S> 121 { 122 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); 123 }; 124 125 template <typename S> 126 struct call_traits<S, 127 typename enable_if< 128 ( 129 !schedule_member<S>::is_valid 130 && 131 !schedule_free<S>::is_valid 132 && 133 is_executor<typename decay<S>::type>::value 134 ) 135 >::type> 136 { 137 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = identity); 138 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 139 140 #if defined(BOOST_ASIO_HAS_MOVE) 141 typedef BOOST_ASIO_MOVE_ARG(S) result_type; 142 #else // defined(BOOST_ASIO_HAS_MOVE) 143 typedef BOOST_ASIO_MOVE_ARG(typename decay<S>::type) result_type; 144 #endif // defined(BOOST_ASIO_HAS_MOVE) 145 }; 146 147 struct impl 148 { 149 template <typename S> 150 BOOST_ASIO_CONSTEXPR typename enable_if< 151 call_traits<S>::overload == identity, 152 typename call_traits<S>::result_type 153 >::type operator ()asio_execution_schedule_fn::impl154 operator()(BOOST_ASIO_MOVE_ARG(S) s) const 155 BOOST_ASIO_NOEXCEPT_IF(( 156 call_traits<S>::is_noexcept)) 157 { 158 return BOOST_ASIO_MOVE_CAST(S)(s); 159 } 160 161 #if defined(BOOST_ASIO_HAS_MOVE) 162 template <typename S> 163 BOOST_ASIO_CONSTEXPR typename enable_if< 164 call_traits<S>::overload == call_member, 165 typename call_traits<S>::result_type 166 >::type operator ()asio_execution_schedule_fn::impl167 operator()(S&& s) const 168 BOOST_ASIO_NOEXCEPT_IF(( 169 call_traits<S>::is_noexcept)) 170 { 171 return BOOST_ASIO_MOVE_CAST(S)(s).schedule(); 172 } 173 174 template <typename S> 175 BOOST_ASIO_CONSTEXPR typename enable_if< 176 call_traits<S>::overload == call_free, 177 typename call_traits<S>::result_type 178 >::type operator ()asio_execution_schedule_fn::impl179 operator()(S&& s) const 180 BOOST_ASIO_NOEXCEPT_IF(( 181 call_traits<S>::is_noexcept)) 182 { 183 return schedule(BOOST_ASIO_MOVE_CAST(S)(s)); 184 } 185 #else // defined(BOOST_ASIO_HAS_MOVE) 186 template <typename S> 187 BOOST_ASIO_CONSTEXPR typename enable_if< 188 call_traits<S&>::overload == call_member, 189 typename call_traits<S&>::result_type 190 >::type operator ()asio_execution_schedule_fn::impl191 operator()(S& s) const 192 BOOST_ASIO_NOEXCEPT_IF(( 193 call_traits<S&>::is_noexcept)) 194 { 195 return s.schedule(); 196 } 197 198 template <typename S> 199 BOOST_ASIO_CONSTEXPR typename enable_if< 200 call_traits<const S&>::overload == call_member, 201 typename call_traits<const S&>::result_type 202 >::type operator ()asio_execution_schedule_fn::impl203 operator()(const S& s) const 204 BOOST_ASIO_NOEXCEPT_IF(( 205 call_traits<const S&>::is_noexcept)) 206 { 207 return s.schedule(); 208 } 209 210 template <typename S> 211 BOOST_ASIO_CONSTEXPR typename enable_if< 212 call_traits<S&>::overload == call_free, 213 typename call_traits<S&>::result_type 214 >::type operator ()asio_execution_schedule_fn::impl215 operator()(S& s) const 216 BOOST_ASIO_NOEXCEPT_IF(( 217 call_traits<S&>::is_noexcept)) 218 { 219 return schedule(s); 220 } 221 222 template <typename S> 223 BOOST_ASIO_CONSTEXPR typename enable_if< 224 call_traits<const S&>::overload == call_free, 225 typename call_traits<const S&>::result_type 226 >::type operator ()asio_execution_schedule_fn::impl227 operator()(const S& s) const 228 BOOST_ASIO_NOEXCEPT_IF(( 229 call_traits<const S&>::is_noexcept)) 230 { 231 return schedule(s); 232 } 233 #endif // defined(BOOST_ASIO_HAS_MOVE) 234 }; 235 236 template <typename T = impl> 237 struct static_instance 238 { 239 static const T instance; 240 }; 241 242 template <typename T> 243 const T static_instance<T>::instance = {}; 244 245 } // namespace asio_execution_schedule_fn 246 namespace boost { 247 namespace asio { 248 namespace execution { 249 namespace { 250 251 static BOOST_ASIO_CONSTEXPR const asio_execution_schedule_fn::impl& 252 schedule = asio_execution_schedule_fn::static_instance<>::instance; 253 254 } // namespace 255 256 template <typename S> 257 struct can_schedule : 258 integral_constant<bool, 259 asio_execution_schedule_fn::call_traits<S>::overload != 260 asio_execution_schedule_fn::ill_formed> 261 { 262 }; 263 264 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 265 266 template <typename S> 267 constexpr bool can_schedule_v = can_schedule<S>::value; 268 269 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 270 271 template <typename S> 272 struct is_nothrow_schedule : 273 integral_constant<bool, 274 asio_execution_schedule_fn::call_traits<S>::is_noexcept> 275 { 276 }; 277 278 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 279 280 template <typename S> 281 constexpr bool is_nothrow_schedule_v 282 = is_nothrow_schedule<S>::value; 283 284 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 285 286 } // namespace execution 287 } // namespace asio 288 } // namespace boost 289 290 #endif // defined(GENERATING_DOCUMENTATION) 291 292 #include <boost/asio/detail/pop_options.hpp> 293 294 #endif // BOOST_ASIO_EXECUTION_SCHEDULE_HPP 295