schedule.hpp 7.0 KB

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