1 // 2 // execution/schedule.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 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, typename = void, 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 schedule_member<S>::is_valid 103 >::type> : 104 schedule_member<S> 105 { 106 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); 107 }; 108 109 template <typename S> 110 struct call_traits<S, 111 typename enable_if< 112 !schedule_member<S>::is_valid 113 >::type, 114 typename enable_if< 115 schedule_free<S>::is_valid 116 >::type> : 117 schedule_free<S> 118 { 119 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); 120 }; 121 122 template <typename S> 123 struct call_traits<S, 124 typename enable_if< 125 !schedule_member<S>::is_valid 126 >::type, 127 typename enable_if< 128 !schedule_free<S>::is_valid 129 >::type, 130 typename enable_if< 131 is_executor<typename decay<S>::type>::value 132 >::type> 133 { 134 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = identity); 135 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 136 137 #if defined(BOOST_ASIO_HAS_MOVE) 138 typedef BOOST_ASIO_MOVE_ARG(S) result_type; 139 #else // defined(BOOST_ASIO_HAS_MOVE) 140 typedef BOOST_ASIO_MOVE_ARG(typename decay<S>::type) result_type; 141 #endif // defined(BOOST_ASIO_HAS_MOVE) 142 }; 143 144 struct impl 145 { 146 template <typename S> 147 BOOST_ASIO_CONSTEXPR typename enable_if< 148 call_traits<S>::overload == identity, 149 typename call_traits<S>::result_type 150 >::type operator ()asio_execution_schedule_fn::impl151 operator()(BOOST_ASIO_MOVE_ARG(S) s) const 152 BOOST_ASIO_NOEXCEPT_IF(( 153 call_traits<S>::is_noexcept)) 154 { 155 return BOOST_ASIO_MOVE_CAST(S)(s); 156 } 157 158 #if defined(BOOST_ASIO_HAS_MOVE) 159 template <typename S> 160 BOOST_ASIO_CONSTEXPR typename enable_if< 161 call_traits<S>::overload == call_member, 162 typename call_traits<S>::result_type 163 >::type operator ()asio_execution_schedule_fn::impl164 operator()(S&& s) const 165 BOOST_ASIO_NOEXCEPT_IF(( 166 call_traits<S>::is_noexcept)) 167 { 168 return BOOST_ASIO_MOVE_CAST(S)(s).schedule(); 169 } 170 171 template <typename S> 172 BOOST_ASIO_CONSTEXPR typename enable_if< 173 call_traits<S>::overload == call_free, 174 typename call_traits<S>::result_type 175 >::type operator ()asio_execution_schedule_fn::impl176 operator()(S&& s) const 177 BOOST_ASIO_NOEXCEPT_IF(( 178 call_traits<S>::is_noexcept)) 179 { 180 return schedule(BOOST_ASIO_MOVE_CAST(S)(s)); 181 } 182 #else // defined(BOOST_ASIO_HAS_MOVE) 183 template <typename S> 184 BOOST_ASIO_CONSTEXPR typename enable_if< 185 call_traits<S&>::overload == call_member, 186 typename call_traits<S&>::result_type 187 >::type operator ()asio_execution_schedule_fn::impl188 operator()(S& s) const 189 BOOST_ASIO_NOEXCEPT_IF(( 190 call_traits<S&>::is_noexcept)) 191 { 192 return s.schedule(); 193 } 194 195 template <typename S> 196 BOOST_ASIO_CONSTEXPR typename enable_if< 197 call_traits<const S&>::overload == call_member, 198 typename call_traits<const S&>::result_type 199 >::type operator ()asio_execution_schedule_fn::impl200 operator()(const S& s) const 201 BOOST_ASIO_NOEXCEPT_IF(( 202 call_traits<const S&>::is_noexcept)) 203 { 204 return s.schedule(); 205 } 206 207 template <typename S> 208 BOOST_ASIO_CONSTEXPR typename enable_if< 209 call_traits<S&>::overload == call_free, 210 typename call_traits<S&>::result_type 211 >::type operator ()asio_execution_schedule_fn::impl212 operator()(S& s) const 213 BOOST_ASIO_NOEXCEPT_IF(( 214 call_traits<S&>::is_noexcept)) 215 { 216 return schedule(s); 217 } 218 219 template <typename S> 220 BOOST_ASIO_CONSTEXPR typename enable_if< 221 call_traits<const S&>::overload == call_free, 222 typename call_traits<const S&>::result_type 223 >::type operator ()asio_execution_schedule_fn::impl224 operator()(const S& s) const 225 BOOST_ASIO_NOEXCEPT_IF(( 226 call_traits<const S&>::is_noexcept)) 227 { 228 return schedule(s); 229 } 230 #endif // defined(BOOST_ASIO_HAS_MOVE) 231 }; 232 233 template <typename T = impl> 234 struct static_instance 235 { 236 static const T instance; 237 }; 238 239 template <typename T> 240 const T static_instance<T>::instance = {}; 241 242 } // namespace asio_execution_schedule_fn 243 namespace boost { 244 namespace asio { 245 namespace execution { 246 namespace { 247 248 static BOOST_ASIO_CONSTEXPR const asio_execution_schedule_fn::impl& 249 schedule = asio_execution_schedule_fn::static_instance<>::instance; 250 251 } // namespace 252 253 template <typename S> 254 struct can_schedule : 255 integral_constant<bool, 256 asio_execution_schedule_fn::call_traits<S>::overload != 257 asio_execution_schedule_fn::ill_formed> 258 { 259 }; 260 261 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 262 263 template <typename S> 264 constexpr bool can_schedule_v = can_schedule<S>::value; 265 266 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 267 268 template <typename S> 269 struct is_nothrow_schedule : 270 integral_constant<bool, 271 asio_execution_schedule_fn::call_traits<S>::is_noexcept> 272 { 273 }; 274 275 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 276 277 template <typename S> 278 constexpr bool is_nothrow_schedule_v 279 = is_nothrow_schedule<S>::value; 280 281 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 282 283 } // namespace execution 284 } // namespace asio 285 } // namespace boost 286 287 #endif // defined(GENERATING_DOCUMENTATION) 288 289 #include <boost/asio/detail/pop_options.hpp> 290 291 #endif // BOOST_ASIO_EXECUTION_SCHEDULE_HPP 292