sender.hpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. //
  2. // execution/sender.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2022 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. #ifndef ASIO_EXECUTION_SENDER_HPP
  11. #define ASIO_EXECUTION_SENDER_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/config.hpp"
  16. #include "asio/detail/type_traits.hpp"
  17. #include "asio/execution/detail/as_invocable.hpp"
  18. #include "asio/execution/detail/void_receiver.hpp"
  19. #include "asio/execution/executor.hpp"
  20. #include "asio/execution/receiver.hpp"
  21. #include "asio/detail/push_options.hpp"
  22. #if defined(ASIO_HAS_ALIAS_TEMPLATES) \
  23. && defined(ASIO_HAS_VARIADIC_TEMPLATES) \
  24. && defined(ASIO_HAS_DECLTYPE) \
  25. && !defined(ASIO_MSVC) || (_MSC_VER >= 1910)
  26. # define ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT 1
  27. #endif // defined(ASIO_HAS_ALIAS_TEMPLATES)
  28. // && defined(ASIO_HAS_VARIADIC_TEMPLATES)
  29. // && defined(ASIO_HAS_DECLTYPE)
  30. // && !defined(ASIO_MSVC) || (_MSC_VER >= 1910)
  31. namespace asio {
  32. namespace execution {
  33. namespace detail {
  34. namespace sender_base_ns { struct sender_base {}; }
  35. template <typename S, typename = void>
  36. struct sender_traits_base
  37. {
  38. typedef void asio_execution_sender_traits_base_is_unspecialised;
  39. };
  40. template <typename S>
  41. struct sender_traits_base<S,
  42. typename enable_if<
  43. is_base_of<sender_base_ns::sender_base, S>::value
  44. >::type>
  45. {
  46. };
  47. template <typename S, typename = void, typename = void, typename = void>
  48. struct has_sender_types : false_type
  49. {
  50. };
  51. #if defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT)
  52. template <
  53. template <
  54. template <typename...> class Tuple,
  55. template <typename...> class Variant
  56. > class>
  57. struct has_value_types
  58. {
  59. typedef void type;
  60. };
  61. template <
  62. template <
  63. template <typename...> class Variant
  64. > class>
  65. struct has_error_types
  66. {
  67. typedef void type;
  68. };
  69. template <typename S>
  70. struct has_sender_types<S,
  71. typename has_value_types<S::template value_types>::type,
  72. typename has_error_types<S::template error_types>::type,
  73. typename conditional<S::sends_done, void, void>::type> : true_type
  74. {
  75. };
  76. template <typename S>
  77. struct sender_traits_base<S,
  78. typename enable_if<
  79. has_sender_types<S>::value
  80. >::type>
  81. {
  82. template <
  83. template <typename...> class Tuple,
  84. template <typename...> class Variant>
  85. using value_types = typename S::template value_types<Tuple, Variant>;
  86. template <template <typename...> class Variant>
  87. using error_types = typename S::template error_types<Variant>;
  88. ASIO_STATIC_CONSTEXPR(bool, sends_done = S::sends_done);
  89. };
  90. #endif // defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT)
  91. template <typename S>
  92. struct sender_traits_base<S,
  93. typename enable_if<
  94. !has_sender_types<S>::value
  95. && detail::is_executor_of_impl<S,
  96. as_invocable<void_receiver, S> >::value
  97. >::type>
  98. {
  99. #if defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) \
  100. && defined(ASIO_HAS_STD_EXCEPTION_PTR)
  101. template <
  102. template <typename...> class Tuple,
  103. template <typename...> class Variant>
  104. using value_types = Variant<Tuple<>>;
  105. template <template <typename...> class Variant>
  106. using error_types = Variant<std::exception_ptr>;
  107. ASIO_STATIC_CONSTEXPR(bool, sends_done = true);
  108. #endif // defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT)
  109. // && defined(ASIO_HAS_STD_EXCEPTION_PTR)
  110. };
  111. } // namespace detail
  112. /// Base class used for tagging senders.
  113. #if defined(GENERATING_DOCUMENTATION)
  114. typedef unspecified sender_base;
  115. #else // defined(GENERATING_DOCUMENTATION)
  116. typedef detail::sender_base_ns::sender_base sender_base;
  117. #endif // defined(GENERATING_DOCUMENTATION)
  118. /// Traits for senders.
  119. template <typename S>
  120. struct sender_traits
  121. #if !defined(GENERATING_DOCUMENTATION)
  122. : detail::sender_traits_base<S>
  123. #endif // !defined(GENERATING_DOCUMENTATION)
  124. {
  125. };
  126. namespace detail {
  127. template <typename S, typename = void>
  128. struct has_sender_traits : true_type
  129. {
  130. };
  131. template <typename S>
  132. struct has_sender_traits<S,
  133. typename enable_if<
  134. is_same<
  135. typename asio::execution::sender_traits<
  136. S>::asio_execution_sender_traits_base_is_unspecialised,
  137. void
  138. >::value
  139. >::type> : false_type
  140. {
  141. };
  142. } // namespace detail
  143. /// The is_sender trait detects whether a type T satisfies the
  144. /// execution::sender concept.
  145. /**
  146. * Class template @c is_sender is a type trait that is derived from @c
  147. * true_type if the type @c T meets the concept definition for a sender,
  148. * otherwise @c false_type.
  149. */
  150. template <typename T>
  151. struct is_sender :
  152. #if defined(GENERATING_DOCUMENTATION)
  153. integral_constant<bool, automatically_determined>
  154. #else // defined(GENERATING_DOCUMENTATION)
  155. conditional<
  156. detail::has_sender_traits<typename remove_cvref<T>::type>::value,
  157. is_move_constructible<typename remove_cvref<T>::type>,
  158. false_type
  159. >::type
  160. #endif // defined(GENERATING_DOCUMENTATION)
  161. {
  162. };
  163. #if defined(ASIO_HAS_VARIABLE_TEMPLATES)
  164. template <typename T>
  165. ASIO_CONSTEXPR const bool is_sender_v = is_sender<T>::value;
  166. #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)
  167. #if defined(ASIO_HAS_CONCEPTS)
  168. template <typename T>
  169. ASIO_CONCEPT sender = is_sender<T>::value;
  170. #define ASIO_EXECUTION_SENDER ::asio::execution::sender
  171. #else // defined(ASIO_HAS_CONCEPTS)
  172. #define ASIO_EXECUTION_SENDER typename
  173. #endif // defined(ASIO_HAS_CONCEPTS)
  174. template <typename S, typename R>
  175. struct can_connect;
  176. /// The is_sender_to trait detects whether a type T satisfies the
  177. /// execution::sender_to concept for some receiver.
  178. /**
  179. * Class template @c is_sender_to 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. * for some receiver type R, otherwise @c false.
  182. */
  183. template <typename T, typename R>
  184. struct is_sender_to :
  185. #if defined(GENERATING_DOCUMENTATION)
  186. integral_constant<bool, automatically_determined>
  187. #else // defined(GENERATING_DOCUMENTATION)
  188. integral_constant<bool,
  189. is_sender<T>::value
  190. && is_receiver<R>::value
  191. && can_connect<T, R>::value
  192. >
  193. #endif // defined(GENERATING_DOCUMENTATION)
  194. {
  195. };
  196. #if defined(ASIO_HAS_VARIABLE_TEMPLATES)
  197. template <typename T, typename R>
  198. ASIO_CONSTEXPR const bool is_sender_to_v =
  199. is_sender_to<T, R>::value;
  200. #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)
  201. #if defined(ASIO_HAS_CONCEPTS)
  202. template <typename T, typename R>
  203. ASIO_CONCEPT sender_to = is_sender_to<T, R>::value;
  204. #define ASIO_EXECUTION_SENDER_TO(r) \
  205. ::asio::execution::sender_to<r>
  206. #else // defined(ASIO_HAS_CONCEPTS)
  207. #define ASIO_EXECUTION_SENDER_TO(r) typename
  208. #endif // defined(ASIO_HAS_CONCEPTS)
  209. /// The is_typed_sender trait detects whether a type T satisfies the
  210. /// execution::typed_sender concept.
  211. /**
  212. * Class template @c is_typed_sender is a type trait that is derived from @c
  213. * true_type if the type @c T meets the concept definition for a typed sender,
  214. * otherwise @c false.
  215. */
  216. template <typename T>
  217. struct is_typed_sender :
  218. #if defined(GENERATING_DOCUMENTATION)
  219. integral_constant<bool, automatically_determined>
  220. #else // defined(GENERATING_DOCUMENTATION)
  221. integral_constant<bool,
  222. is_sender<T>::value
  223. && detail::has_sender_types<
  224. sender_traits<typename remove_cvref<T>::type> >::value
  225. >
  226. #endif // defined(GENERATING_DOCUMENTATION)
  227. {
  228. };
  229. #if defined(ASIO_HAS_VARIABLE_TEMPLATES)
  230. template <typename T>
  231. ASIO_CONSTEXPR const bool is_typed_sender_v = is_typed_sender<T>::value;
  232. #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)
  233. #if defined(ASIO_HAS_CONCEPTS)
  234. template <typename T>
  235. ASIO_CONCEPT typed_sender = is_typed_sender<T>::value;
  236. #define ASIO_EXECUTION_TYPED_SENDER \
  237. ::asio::execution::typed_sender
  238. #else // defined(ASIO_HAS_CONCEPTS)
  239. #define ASIO_EXECUTION_TYPED_SENDER typename
  240. #endif // defined(ASIO_HAS_CONCEPTS)
  241. } // namespace execution
  242. } // namespace asio
  243. #include "asio/detail/pop_options.hpp"
  244. #include "asio/execution/connect.hpp"
  245. #endif // ASIO_EXECUTION_SENDER_HPP