1 // 2 // execution/sender.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_SENDER_HPP 12 #define BOOST_ASIO_EXECUTION_SENDER_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/void_receiver.hpp> 22 #include <boost/asio/execution/executor.hpp> 23 #include <boost/asio/execution/receiver.hpp> 24 25 #include <boost/asio/detail/push_options.hpp> 26 27 #if defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES) \ 28 && defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) \ 29 && defined(BOOST_ASIO_HAS_DECLTYPE) \ 30 && !defined(BOOST_ASIO_MSVC) || (_MSC_VER >= 1910) 31 # define BOOST_ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT 1 32 #endif // defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES) 33 // && defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 34 // && defined(BOOST_ASIO_HAS_DECLTYPE) 35 // && !defined(BOOST_ASIO_MSVC) || (_MSC_VER >= 1910) 36 37 namespace boost { 38 namespace asio { 39 namespace execution { 40 namespace detail { 41 42 namespace sender_base_ns { struct sender_base {}; } 43 44 template <typename S, typename = void> 45 struct sender_traits_base 46 { 47 typedef void asio_execution_sender_traits_base_is_unspecialised; 48 }; 49 50 template <typename S> 51 struct sender_traits_base<S, 52 typename enable_if< 53 is_base_of<sender_base_ns::sender_base, S>::value 54 >::type> 55 { 56 }; 57 58 template <typename S, typename = void, typename = void, typename = void> 59 struct has_sender_types : false_type 60 { 61 }; 62 63 #if defined(BOOST_ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) 64 65 template < 66 template < 67 template <typename...> class Tuple, 68 template <typename...> class Variant 69 > class> 70 struct has_value_types 71 { 72 typedef void type; 73 }; 74 75 template < 76 template < 77 template <typename...> class Variant 78 > class> 79 struct has_error_types 80 { 81 typedef void type; 82 }; 83 84 template <typename S> 85 struct has_sender_types<S, 86 typename has_value_types<S::template value_types>::type, 87 typename has_error_types<S::template error_types>::type, 88 typename conditional<S::sends_done, void, void>::type> : true_type 89 { 90 }; 91 92 template <typename S> 93 struct sender_traits_base<S, 94 typename enable_if< 95 has_sender_types<S>::value 96 >::type> 97 { 98 template < 99 template <typename...> class Tuple, 100 template <typename...> class Variant> 101 using value_types = typename S::template value_types<Tuple, Variant>; 102 103 template <template <typename...> class Variant> 104 using error_types = typename S::template error_types<Variant>; 105 106 BOOST_ASIO_STATIC_CONSTEXPR(bool, sends_done = S::sends_done); 107 }; 108 109 #endif // defined(BOOST_ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) 110 111 template <typename S> 112 struct sender_traits_base<S, 113 typename enable_if< 114 !has_sender_types<S>::value 115 && detail::is_executor_of_impl<S, 116 as_invocable<void_receiver, S> >::value 117 >::type> 118 { 119 #if defined(BOOST_ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) \ 120 && defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) 121 122 template < 123 template <typename...> class Tuple, 124 template <typename...> class Variant> 125 using value_types = Variant<Tuple<>>; 126 127 template <template <typename...> class Variant> 128 using error_types = Variant<std::exception_ptr>; 129 130 BOOST_ASIO_STATIC_CONSTEXPR(bool, sends_done = true); 131 132 #endif // defined(BOOST_ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) 133 // && defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) 134 }; 135 136 } // namespace detail 137 138 /// Base class used for tagging senders. 139 #if defined(GENERATING_DOCUMENTATION) 140 typedef unspecified sender_base; 141 #else // defined(GENERATING_DOCUMENTATION) 142 typedef detail::sender_base_ns::sender_base sender_base; 143 #endif // defined(GENERATING_DOCUMENTATION) 144 145 /// Traits for senders. 146 template <typename S> 147 struct sender_traits 148 #if !defined(GENERATING_DOCUMENTATION) 149 : detail::sender_traits_base<S> 150 #endif // !defined(GENERATING_DOCUMENTATION) 151 { 152 }; 153 154 namespace detail { 155 156 template <typename S, typename = void> 157 struct has_sender_traits : true_type 158 { 159 }; 160 161 template <typename S> 162 struct has_sender_traits<S, 163 typename enable_if< 164 is_same< 165 typename boost::asio::execution::sender_traits< 166 S>::asio_execution_sender_traits_base_is_unspecialised, 167 void 168 >::value 169 >::type> : false_type 170 { 171 }; 172 173 } // namespace detail 174 175 /// The is_sender trait detects whether a type T satisfies the 176 /// execution::sender concept. 177 178 /** 179 * Class template @c is_sender is a type trait that is derived from @c 180 * true_type if the type @c T meets the concept definition for a sender, 181 * otherwise @c false_type. 182 */ 183 template <typename T> 184 struct is_sender : 185 #if defined(GENERATING_DOCUMENTATION) 186 integral_constant<bool, automatically_determined> 187 #else // defined(GENERATING_DOCUMENTATION) 188 conditional< 189 detail::has_sender_traits<typename remove_cvref<T>::type>::value, 190 is_move_constructible<typename remove_cvref<T>::type>, 191 false_type 192 >::type 193 #endif // defined(GENERATING_DOCUMENTATION) 194 { 195 }; 196 197 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 198 199 template <typename T> 200 BOOST_ASIO_CONSTEXPR const bool is_sender_v = is_sender<T>::value; 201 202 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 203 204 #if defined(BOOST_ASIO_HAS_CONCEPTS) 205 206 template <typename T> 207 BOOST_ASIO_CONCEPT sender = is_sender<T>::value; 208 209 #define BOOST_ASIO_EXECUTION_SENDER ::boost::asio::execution::sender 210 211 #else // defined(BOOST_ASIO_HAS_CONCEPTS) 212 213 #define BOOST_ASIO_EXECUTION_SENDER typename 214 215 #endif // defined(BOOST_ASIO_HAS_CONCEPTS) 216 217 template <typename S, typename R> 218 struct can_connect; 219 220 /// The is_sender_to trait detects whether a type T satisfies the 221 /// execution::sender_to concept for some receiver. 222 /** 223 * Class template @c is_sender_to is a type trait that is derived from @c 224 * true_type if the type @c T meets the concept definition for a sender 225 * for some receiver type R, otherwise @c false. 226 */ 227 template <typename T, typename R> 228 struct is_sender_to : 229 #if defined(GENERATING_DOCUMENTATION) 230 integral_constant<bool, automatically_determined> 231 #else // defined(GENERATING_DOCUMENTATION) 232 integral_constant<bool, 233 is_sender<T>::value 234 && is_receiver<R>::value 235 && can_connect<T, R>::value 236 > 237 #endif // defined(GENERATING_DOCUMENTATION) 238 { 239 }; 240 241 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 242 243 template <typename T, typename R> 244 BOOST_ASIO_CONSTEXPR const bool is_sender_to_v = 245 is_sender_to<T, R>::value; 246 247 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 248 249 #if defined(BOOST_ASIO_HAS_CONCEPTS) 250 251 template <typename T, typename R> 252 BOOST_ASIO_CONCEPT sender_to = is_sender_to<T, R>::value; 253 254 #define BOOST_ASIO_EXECUTION_SENDER_TO(r) \ 255 ::boost::asio::execution::sender_to<r> 256 257 #else // defined(BOOST_ASIO_HAS_CONCEPTS) 258 259 #define BOOST_ASIO_EXECUTION_SENDER_TO(r) typename 260 261 #endif // defined(BOOST_ASIO_HAS_CONCEPTS) 262 263 /// The is_typed_sender trait detects whether a type T satisfies the 264 /// execution::typed_sender concept. 265 /** 266 * Class template @c is_typed_sender is a type trait that is derived from @c 267 * true_type if the type @c T meets the concept definition for a typed sender, 268 * otherwise @c false. 269 */ 270 template <typename T> 271 struct is_typed_sender : 272 #if defined(GENERATING_DOCUMENTATION) 273 integral_constant<bool, automatically_determined> 274 #else // defined(GENERATING_DOCUMENTATION) 275 integral_constant<bool, 276 is_sender<T>::value 277 && detail::has_sender_types< 278 sender_traits<typename remove_cvref<T>::type> >::value 279 > 280 #endif // defined(GENERATING_DOCUMENTATION) 281 { 282 }; 283 284 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 285 286 template <typename T> 287 BOOST_ASIO_CONSTEXPR const bool is_typed_sender_v = is_typed_sender<T>::value; 288 289 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 290 291 #if defined(BOOST_ASIO_HAS_CONCEPTS) 292 293 template <typename T> 294 BOOST_ASIO_CONCEPT typed_sender = is_typed_sender<T>::value; 295 296 #define BOOST_ASIO_EXECUTION_TYPED_SENDER \ 297 ::boost::asio::execution::typed_sender 298 299 #else // defined(BOOST_ASIO_HAS_CONCEPTS) 300 301 #define BOOST_ASIO_EXECUTION_TYPED_SENDER typename 302 303 #endif // defined(BOOST_ASIO_HAS_CONCEPTS) 304 305 } // namespace execution 306 } // namespace asio 307 } // namespace boost 308 309 #include <boost/asio/detail/pop_options.hpp> 310 311 #include <boost/asio/execution/connect.hpp> 312 313 #endif // BOOST_ASIO_EXECUTION_SENDER_HPP 314