submit.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. //
  2. // execution/submit.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. #ifndef BOOST_ASIO_EXECUTION_SUBMIT_HPP
  11. #define BOOST_ASIO_EXECUTION_SUBMIT_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <boost/asio/detail/type_traits.hpp>
  17. #include <boost/asio/execution/detail/submit_receiver.hpp>
  18. #include <boost/asio/execution/executor.hpp>
  19. #include <boost/asio/execution/receiver.hpp>
  20. #include <boost/asio/execution/sender.hpp>
  21. #include <boost/asio/execution/start.hpp>
  22. #include <boost/asio/traits/submit_member.hpp>
  23. #include <boost/asio/traits/submit_free.hpp>
  24. #include <boost/asio/detail/push_options.hpp>
  25. #if defined(GENERATING_DOCUMENTATION)
  26. namespace boost {
  27. namespace asio {
  28. namespace execution {
  29. /// A customisation point that submits a sender to a receiver.
  30. /**
  31. * The name <tt>execution::submit</tt> denotes a customisation point object. For
  32. * some subexpressions <tt>s</tt> and <tt>r</tt>, let <tt>S</tt> be a type such
  33. * that <tt>decltype((s))</tt> is <tt>S</tt> and let <tt>R</tt> be a type such
  34. * that <tt>decltype((r))</tt> is <tt>R</tt>. The expression
  35. * <tt>execution::submit(s, r)</tt> is ill-formed if <tt>sender_to<S, R></tt> is
  36. * not <tt>true</tt>. Otherwise, it is expression-equivalent to:
  37. *
  38. * @li <tt>s.submit(r)</tt>, if that expression is valid and <tt>S</tt> models
  39. * <tt>sender</tt>. If the function selected does not submit the receiver
  40. * object <tt>r</tt> via the sender <tt>s</tt>, the program is ill-formed with
  41. * no diagnostic required.
  42. *
  43. * @li Otherwise, <tt>submit(s, r)</tt>, if that expression is valid and
  44. * <tt>S</tt> models <tt>sender</tt>, with overload resolution performed in a
  45. * context that includes the declaration <tt>void submit();</tt> and that does
  46. * not include a declaration of <tt>execution::submit</tt>. If the function
  47. * selected by overload resolution does not submit the receiver object
  48. * <tt>r</tt> via the sender <tt>s</tt>, the program is ill-formed with no
  49. * diagnostic required.
  50. *
  51. * @li Otherwise, <tt>execution::start((new submit_receiver<S,
  52. * R>{s,r})->state_)</tt>, where <tt>submit_receiver</tt> is an
  53. * implementation-defined class template equivalent to:
  54. * @code template<class S, class R>
  55. * struct submit_receiver {
  56. * struct wrap {
  57. * submit_receiver * p_;
  58. * template<class...As>
  59. * requires receiver_of<R, As...>
  60. * void set_value(As&&... as) &&
  61. * noexcept(is_nothrow_receiver_of_v<R, As...>) {
  62. * execution::set_value(std::move(p_->r_), (As&&) as...);
  63. * delete p_;
  64. * }
  65. * template<class E>
  66. * requires receiver<R, E>
  67. * void set_error(E&& e) && noexcept {
  68. * execution::set_error(std::move(p_->r_), (E&&) e);
  69. * delete p_;
  70. * }
  71. * void set_done() && noexcept {
  72. * execution::set_done(std::move(p_->r_));
  73. * delete p_;
  74. * }
  75. * };
  76. * remove_cvref_t<R> r_;
  77. * connect_result_t<S, wrap> state_;
  78. * submit_receiver(S&& s, R&& r)
  79. * : r_((R&&) r)
  80. * , state_(execution::connect((S&&) s, wrap{this})) {}
  81. * };
  82. * @endcode
  83. */
  84. inline constexpr unspecified submit = unspecified;
  85. /// A type trait that determines whether a @c submit expression is
  86. /// well-formed.
  87. /**
  88. * Class template @c can_submit is a trait that is derived from
  89. * @c true_type if the expression <tt>execution::submit(std::declval<R>(),
  90. * std::declval<E>())</tt> is well formed; otherwise @c false_type.
  91. */
  92. template <typename S, typename R>
  93. struct can_submit :
  94. integral_constant<bool, automatically_determined>
  95. {
  96. };
  97. } // namespace execution
  98. } // namespace asio
  99. } // namespace boost
  100. #else // defined(GENERATING_DOCUMENTATION)
  101. namespace asio_execution_submit_fn {
  102. using boost::asio::declval;
  103. using boost::asio::enable_if;
  104. using boost::asio::execution::is_sender_to;
  105. using boost::asio::traits::submit_free;
  106. using boost::asio::traits::submit_member;
  107. void submit();
  108. enum overload_type
  109. {
  110. call_member,
  111. call_free,
  112. adapter,
  113. ill_formed
  114. };
  115. template <typename S, typename R, typename = void,
  116. typename = void, typename = void>
  117. struct call_traits
  118. {
  119. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);
  120. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
  121. typedef void result_type;
  122. };
  123. template <typename S, typename R>
  124. struct call_traits<S, void(R),
  125. typename enable_if<
  126. submit_member<S, R>::is_valid
  127. >::type,
  128. typename enable_if<
  129. is_sender_to<S, R>::value
  130. >::type> :
  131. submit_member<S, R>
  132. {
  133. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);
  134. };
  135. template <typename S, typename R>
  136. struct call_traits<S, void(R),
  137. typename enable_if<
  138. !submit_member<S, R>::is_valid
  139. >::type,
  140. typename enable_if<
  141. submit_free<S, R>::is_valid
  142. >::type,
  143. typename enable_if<
  144. is_sender_to<S, R>::value
  145. >::type> :
  146. submit_free<S, R>
  147. {
  148. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);
  149. };
  150. template <typename S, typename R>
  151. struct call_traits<S, void(R),
  152. typename enable_if<
  153. !submit_member<S, R>::is_valid
  154. >::type,
  155. typename enable_if<
  156. !submit_free<S, R>::is_valid
  157. >::type,
  158. typename enable_if<
  159. is_sender_to<S, R>::value
  160. >::type>
  161. {
  162. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter);
  163. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
  164. typedef void result_type;
  165. };
  166. struct impl
  167. {
  168. #if defined(BOOST_ASIO_HAS_MOVE)
  169. template <typename S, typename R>
  170. BOOST_ASIO_CONSTEXPR typename enable_if<
  171. call_traits<S, void(R)>::overload == call_member,
  172. typename call_traits<S, void(R)>::result_type
  173. >::type
  174. operator()(S&& s, R&& r) const
  175. BOOST_ASIO_NOEXCEPT_IF((
  176. call_traits<S, void(R)>::is_noexcept))
  177. {
  178. return BOOST_ASIO_MOVE_CAST(S)(s).submit(BOOST_ASIO_MOVE_CAST(R)(r));
  179. }
  180. template <typename S, typename R>
  181. BOOST_ASIO_CONSTEXPR typename enable_if<
  182. call_traits<S, void(R)>::overload == call_free,
  183. typename call_traits<S, void(R)>::result_type
  184. >::type
  185. operator()(S&& s, R&& r) const
  186. BOOST_ASIO_NOEXCEPT_IF((
  187. call_traits<S, void(R)>::is_noexcept))
  188. {
  189. return submit(BOOST_ASIO_MOVE_CAST(S)(s), BOOST_ASIO_MOVE_CAST(R)(r));
  190. }
  191. template <typename S, typename R>
  192. BOOST_ASIO_CONSTEXPR typename enable_if<
  193. call_traits<S, void(R)>::overload == adapter,
  194. typename call_traits<S, void(R)>::result_type
  195. >::type
  196. operator()(S&& s, R&& r) const
  197. BOOST_ASIO_NOEXCEPT_IF((
  198. call_traits<S, void(R)>::is_noexcept))
  199. {
  200. return boost::asio::execution::start(
  201. (new boost::asio::execution::detail::submit_receiver<S, R>(
  202. BOOST_ASIO_MOVE_CAST(S)(s), BOOST_ASIO_MOVE_CAST(R)(r)))->state_);
  203. }
  204. #else // defined(BOOST_ASIO_HAS_MOVE)
  205. template <typename S, typename R>
  206. BOOST_ASIO_CONSTEXPR typename enable_if<
  207. call_traits<S&, void(R&)>::overload == call_member,
  208. typename call_traits<S&, void(R&)>::result_type
  209. >::type
  210. operator()(S& s, R& r) const
  211. BOOST_ASIO_NOEXCEPT_IF((
  212. call_traits<S&, void(R&)>::is_noexcept))
  213. {
  214. return s.submit(r);
  215. }
  216. template <typename S, typename R>
  217. BOOST_ASIO_CONSTEXPR typename enable_if<
  218. call_traits<const S&, void(R&)>::overload == call_member,
  219. typename call_traits<const S&, void(R&)>::result_type
  220. >::type
  221. operator()(const S& s, R& r) const
  222. BOOST_ASIO_NOEXCEPT_IF((
  223. call_traits<const S&, void(R&)>::is_noexcept))
  224. {
  225. return s.submit(r);
  226. }
  227. template <typename S, typename R>
  228. BOOST_ASIO_CONSTEXPR typename enable_if<
  229. call_traits<S&, void(R&)>::overload == call_free,
  230. typename call_traits<S&, void(R&)>::result_type
  231. >::type
  232. operator()(S& s, R& r) const
  233. BOOST_ASIO_NOEXCEPT_IF((
  234. call_traits<S&, void(R&)>::is_noexcept))
  235. {
  236. return submit(s, r);
  237. }
  238. template <typename S, typename R>
  239. BOOST_ASIO_CONSTEXPR typename enable_if<
  240. call_traits<const S&, void(R&)>::overload == call_free,
  241. typename call_traits<const S&, void(R&)>::result_type
  242. >::type
  243. operator()(const S& s, R& r) const
  244. BOOST_ASIO_NOEXCEPT_IF((
  245. call_traits<const S&, void(R&)>::is_noexcept))
  246. {
  247. return submit(s, r);
  248. }
  249. template <typename S, typename R>
  250. BOOST_ASIO_CONSTEXPR typename enable_if<
  251. call_traits<S&, void(R&)>::overload == adapter,
  252. typename call_traits<S&, void(R&)>::result_type
  253. >::type
  254. operator()(S& s, R& r) const
  255. BOOST_ASIO_NOEXCEPT_IF((
  256. call_traits<S&, void(R&)>::is_noexcept))
  257. {
  258. return boost::asio::execution::start(
  259. (new boost::asio::execution::detail::submit_receiver<
  260. S&, R&>(s, r))->state_);
  261. }
  262. template <typename S, typename R>
  263. BOOST_ASIO_CONSTEXPR typename enable_if<
  264. call_traits<const S&, void(R&)>::overload == adapter,
  265. typename call_traits<const S&, void(R&)>::result_type
  266. >::type
  267. operator()(const S& s, R& r) const
  268. BOOST_ASIO_NOEXCEPT_IF((
  269. call_traits<const S&, void(R&)>::is_noexcept))
  270. {
  271. boost::asio::execution::start(
  272. (new boost::asio::execution::detail::submit_receiver<
  273. const S&, R&>(s, r))->state_);
  274. }
  275. template <typename S, typename R>
  276. BOOST_ASIO_CONSTEXPR typename enable_if<
  277. call_traits<S&, void(const R&)>::overload == call_member,
  278. typename call_traits<S&, void(const R&)>::result_type
  279. >::type
  280. operator()(S& s, const R& r) const
  281. BOOST_ASIO_NOEXCEPT_IF((
  282. call_traits<S&, void(const R&)>::is_noexcept))
  283. {
  284. return s.submit(r);
  285. }
  286. template <typename S, typename R>
  287. BOOST_ASIO_CONSTEXPR typename enable_if<
  288. call_traits<const S&, void(const R&)>::overload == call_member,
  289. typename call_traits<const S&, void(const R&)>::result_type
  290. >::type
  291. operator()(const S& s, const R& r) const
  292. BOOST_ASIO_NOEXCEPT_IF((
  293. call_traits<const S&, void(const R&)>::is_noexcept))
  294. {
  295. return s.submit(r);
  296. }
  297. template <typename S, typename R>
  298. BOOST_ASIO_CONSTEXPR typename enable_if<
  299. call_traits<S&, void(const R&)>::overload == call_free,
  300. typename call_traits<S&, void(const R&)>::result_type
  301. >::type
  302. operator()(S& s, const R& r) const
  303. BOOST_ASIO_NOEXCEPT_IF((
  304. call_traits<S&, void(const R&)>::is_noexcept))
  305. {
  306. return submit(s, r);
  307. }
  308. template <typename S, typename R>
  309. BOOST_ASIO_CONSTEXPR typename enable_if<
  310. call_traits<const S&, void(const R&)>::overload == call_free,
  311. typename call_traits<const S&, void(const R&)>::result_type
  312. >::type
  313. operator()(const S& s, const R& r) const
  314. BOOST_ASIO_NOEXCEPT_IF((
  315. call_traits<const S&, void(const R&)>::is_noexcept))
  316. {
  317. return submit(s, r);
  318. }
  319. template <typename S, typename R>
  320. BOOST_ASIO_CONSTEXPR typename enable_if<
  321. call_traits<S&, void(const R&)>::overload == adapter,
  322. typename call_traits<S&, void(const R&)>::result_type
  323. >::type
  324. operator()(S& s, const R& r) const
  325. BOOST_ASIO_NOEXCEPT_IF((
  326. call_traits<S&, void(const R&)>::is_noexcept))
  327. {
  328. boost::asio::execution::start(
  329. (new boost::asio::execution::detail::submit_receiver<
  330. S&, const R&>(s, r))->state_);
  331. }
  332. template <typename S, typename R>
  333. BOOST_ASIO_CONSTEXPR typename enable_if<
  334. call_traits<const S&, void(const R&)>::overload == adapter,
  335. typename call_traits<const S&, void(const R&)>::result_type
  336. >::type
  337. operator()(const S& s, const R& r) const
  338. BOOST_ASIO_NOEXCEPT_IF((
  339. call_traits<const S&, void(const R&)>::is_noexcept))
  340. {
  341. boost::asio::execution::start(
  342. (new boost::asio::execution::detail::submit_receiver<
  343. const S&, const R&>(s, r))->state_);
  344. }
  345. #endif // defined(BOOST_ASIO_HAS_MOVE)
  346. };
  347. template <typename T = impl>
  348. struct static_instance
  349. {
  350. static const T instance;
  351. };
  352. template <typename T>
  353. const T static_instance<T>::instance = {};
  354. } // namespace asio_execution_submit_fn
  355. namespace boost {
  356. namespace asio {
  357. namespace execution {
  358. namespace {
  359. static BOOST_ASIO_CONSTEXPR const asio_execution_submit_fn::impl&
  360. submit = asio_execution_submit_fn::static_instance<>::instance;
  361. } // namespace
  362. template <typename S, typename R>
  363. struct can_submit :
  364. integral_constant<bool,
  365. asio_execution_submit_fn::call_traits<S, void(R)>::overload !=
  366. asio_execution_submit_fn::ill_formed>
  367. {
  368. };
  369. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  370. template <typename S, typename R>
  371. constexpr bool can_submit_v = can_submit<S, R>::value;
  372. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  373. template <typename S, typename R>
  374. struct is_nothrow_submit :
  375. integral_constant<bool,
  376. asio_execution_submit_fn::call_traits<S, void(R)>::is_noexcept>
  377. {
  378. };
  379. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  380. template <typename S, typename R>
  381. constexpr bool is_nothrow_submit_v
  382. = is_nothrow_submit<S, R>::value;
  383. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  384. template <typename S, typename R>
  385. struct submit_result
  386. {
  387. typedef typename asio_execution_submit_fn::call_traits<
  388. S, void(R)>::result_type type;
  389. };
  390. namespace detail {
  391. template <typename S, typename R>
  392. void submit_helper(BOOST_ASIO_MOVE_ARG(S) s, BOOST_ASIO_MOVE_ARG(R) r)
  393. {
  394. execution::submit(BOOST_ASIO_MOVE_CAST(S)(s), BOOST_ASIO_MOVE_CAST(R)(r));
  395. }
  396. } // namespace detail
  397. } // namespace execution
  398. } // namespace asio
  399. } // namespace boost
  400. #endif // defined(GENERATING_DOCUMENTATION)
  401. #include <boost/asio/detail/pop_options.hpp>
  402. #endif // BOOST_ASIO_EXECUTION_SUBMIT_HPP