submit.hpp 13 KB

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