2 // execution/submit.hpp
3 // ~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_EXECUTION_SUBMIT_HPP
12 #define BOOST_ASIO_EXECUTION_SUBMIT_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
19 #include <boost/asio/detail/type_traits.hpp>
20 #include <boost/asio/execution/detail/submit_receiver.hpp>
21 #include <boost/asio/execution/executor.hpp>
22 #include <boost/asio/execution/receiver.hpp>
23 #include <boost/asio/execution/sender.hpp>
24 #include <boost/asio/execution/start.hpp>
25 #include <boost/asio/traits/submit_member.hpp>
26 #include <boost/asio/traits/submit_free.hpp>
28 #include <boost/asio/detail/push_options.hpp>
30 #if defined(GENERATING_DOCUMENTATION)
36 /// A customisation point that submits a sender to a receiver.
38 * The name <tt>execution::submit</tt> denotes a customisation point object. For
39 * some subexpressions <tt>s</tt> and <tt>r</tt>, let <tt>S</tt> be a type such
40 * that <tt>decltype((s))</tt> is <tt>S</tt> and let <tt>R</tt> be a type such
41 * that <tt>decltype((r))</tt> is <tt>R</tt>. The expression
42 * <tt>execution::submit(s, r)</tt> is ill-formed if <tt>sender_to<S, R></tt> is
43 * not <tt>true</tt>. Otherwise, it is expression-equivalent to:
45 * @li <tt>s.submit(r)</tt>, if that expression is valid and <tt>S</tt> models
46 * <tt>sender</tt>. If the function selected does not submit the receiver
47 * object <tt>r</tt> via the sender <tt>s</tt>, the program is ill-formed with
48 * no diagnostic required.
50 * @li Otherwise, <tt>submit(s, r)</tt>, if that expression is valid and
51 * <tt>S</tt> models <tt>sender</tt>, with overload resolution performed in a
52 * context that includes the declaration <tt>void submit();</tt> and that does
53 * not include a declaration of <tt>execution::submit</tt>. If the function
54 * selected by overload resolution does not submit the receiver object
55 * <tt>r</tt> via the sender <tt>s</tt>, the program is ill-formed with no
56 * diagnostic required.
58 * @li Otherwise, <tt>execution::start((new submit_receiver<S,
59 * R>{s,r})->state_)</tt>, where <tt>submit_receiver</tt> is an
60 * implementation-defined class template equivalent to:
61 * @code template<class S, class R>
62 * struct submit_receiver {
64 * submit_receiver * p_;
65 * template<class...As>
66 * requires receiver_of<R, As...>
67 * void set_value(As&&... as) &&
68 * noexcept(is_nothrow_receiver_of_v<R, As...>) {
69 * execution::set_value(std::move(p_->r_), (As&&) as...);
73 * requires receiver<R, E>
74 * void set_error(E&& e) && noexcept {
75 * execution::set_error(std::move(p_->r_), (E&&) e);
78 * void set_done() && noexcept {
79 * execution::set_done(std::move(p_->r_));
83 * remove_cvref_t<R> r_;
84 * connect_result_t<S, wrap> state_;
85 * submit_receiver(S&& s, R&& r)
87 * , state_(execution::connect((S&&) s, wrap{this})) {}
91 inline constexpr unspecified submit = unspecified;
93 /// A type trait that determines whether a @c submit expression is
96 * Class template @c can_submit is a trait that is derived from
97 * @c true_type if the expression <tt>execution::submit(std::declval<R>(),
98 * std::declval<E>())</tt> is well formed; otherwise @c false_type.
100 template <typename S, typename R>
102 integral_constant<bool, automatically_determined>
106 } // namespace execution
110 #else // defined(GENERATING_DOCUMENTATION)
112 namespace asio_execution_submit_fn {
114 using boost::asio::declval;
115 using boost::asio::enable_if;
116 using boost::asio::execution::is_sender_to;
117 using boost::asio::traits::submit_free;
118 using boost::asio::traits::submit_member;
130 template <typename S, typename R, typename = void>
133 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);
134 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
135 typedef void result_type;
138 template <typename S, typename R>
139 struct call_traits<S, void(R),
142 submit_member<S, R>::is_valid
144 is_sender_to<S, R>::value
149 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);
152 template <typename S, typename R>
153 struct call_traits<S, void(R),
156 !submit_member<S, R>::is_valid
158 submit_free<S, R>::is_valid
160 is_sender_to<S, R>::value
165 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);
168 template <typename S, typename R>
169 struct call_traits<S, void(R),
172 !submit_member<S, R>::is_valid
174 !submit_free<S, R>::is_valid
176 is_sender_to<S, R>::value
180 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter);
181 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
182 typedef void result_type;
187 #if defined(BOOST_ASIO_HAS_MOVE)
188 template <typename S, typename R>
189 BOOST_ASIO_CONSTEXPR typename enable_if<
190 call_traits<S, void(R)>::overload == call_member,
191 typename call_traits<S, void(R)>::result_type
193 operator()(S&& s, R&& r) const
194 BOOST_ASIO_NOEXCEPT_IF((
195 call_traits<S, void(R)>::is_noexcept))
197 return BOOST_ASIO_MOVE_CAST(S)(s).submit(BOOST_ASIO_MOVE_CAST(R)(r));
200 template <typename S, typename R>
201 BOOST_ASIO_CONSTEXPR typename enable_if<
202 call_traits<S, void(R)>::overload == call_free,
203 typename call_traits<S, void(R)>::result_type
205 operator()(S&& s, R&& r) const
206 BOOST_ASIO_NOEXCEPT_IF((
207 call_traits<S, void(R)>::is_noexcept))
209 return submit(BOOST_ASIO_MOVE_CAST(S)(s), BOOST_ASIO_MOVE_CAST(R)(r));
212 template <typename S, typename R>
213 BOOST_ASIO_CONSTEXPR typename enable_if<
214 call_traits<S, void(R)>::overload == adapter,
215 typename call_traits<S, void(R)>::result_type
217 operator()(S&& s, R&& r) const
218 BOOST_ASIO_NOEXCEPT_IF((
219 call_traits<S, void(R)>::is_noexcept))
221 return boost::asio::execution::start(
222 (new boost::asio::execution::detail::submit_receiver<S, R>(
223 BOOST_ASIO_MOVE_CAST(S)(s), BOOST_ASIO_MOVE_CAST(R)(r)))->state_);
225 #else // defined(BOOST_ASIO_HAS_MOVE)
226 template <typename S, typename R>
227 BOOST_ASIO_CONSTEXPR typename enable_if<
228 call_traits<S&, void(R&)>::overload == call_member,
229 typename call_traits<S&, void(R&)>::result_type
231 operator()(S& s, R& r) const
232 BOOST_ASIO_NOEXCEPT_IF((
233 call_traits<S&, void(R&)>::is_noexcept))
238 template <typename S, typename R>
239 BOOST_ASIO_CONSTEXPR typename enable_if<
240 call_traits<const S&, void(R&)>::overload == call_member,
241 typename call_traits<const S&, void(R&)>::result_type
243 operator()(const S& s, R& r) const
244 BOOST_ASIO_NOEXCEPT_IF((
245 call_traits<const S&, void(R&)>::is_noexcept))
250 template <typename S, typename R>
251 BOOST_ASIO_CONSTEXPR typename enable_if<
252 call_traits<S&, void(R&)>::overload == call_free,
253 typename call_traits<S&, void(R&)>::result_type
255 operator()(S& s, R& r) const
256 BOOST_ASIO_NOEXCEPT_IF((
257 call_traits<S&, void(R&)>::is_noexcept))
262 template <typename S, typename R>
263 BOOST_ASIO_CONSTEXPR typename enable_if<
264 call_traits<const S&, void(R&)>::overload == call_free,
265 typename call_traits<const S&, void(R&)>::result_type
267 operator()(const S& s, R& r) const
268 BOOST_ASIO_NOEXCEPT_IF((
269 call_traits<const S&, void(R&)>::is_noexcept))
274 template <typename S, typename R>
275 BOOST_ASIO_CONSTEXPR typename enable_if<
276 call_traits<S&, void(R&)>::overload == adapter,
277 typename call_traits<S&, void(R&)>::result_type
279 operator()(S& s, R& r) const
280 BOOST_ASIO_NOEXCEPT_IF((
281 call_traits<S&, void(R&)>::is_noexcept))
283 return boost::asio::execution::start(
284 (new boost::asio::execution::detail::submit_receiver<
285 S&, R&>(s, r))->state_);
288 template <typename S, typename R>
289 BOOST_ASIO_CONSTEXPR typename enable_if<
290 call_traits<const S&, void(R&)>::overload == adapter,
291 typename call_traits<const S&, void(R&)>::result_type
293 operator()(const S& s, R& r) const
294 BOOST_ASIO_NOEXCEPT_IF((
295 call_traits<const S&, void(R&)>::is_noexcept))
297 boost::asio::execution::start(
298 (new boost::asio::execution::detail::submit_receiver<
299 const S&, R&>(s, r))->state_);
302 template <typename S, typename R>
303 BOOST_ASIO_CONSTEXPR typename enable_if<
304 call_traits<S&, void(const R&)>::overload == call_member,
305 typename call_traits<S&, void(const R&)>::result_type
307 operator()(S& s, const R& r) const
308 BOOST_ASIO_NOEXCEPT_IF((
309 call_traits<S&, void(const R&)>::is_noexcept))
314 template <typename S, typename R>
315 BOOST_ASIO_CONSTEXPR typename enable_if<
316 call_traits<const S&, void(const R&)>::overload == call_member,
317 typename call_traits<const S&, void(const R&)>::result_type
319 operator()(const S& s, const R& r) const
320 BOOST_ASIO_NOEXCEPT_IF((
321 call_traits<const S&, void(const R&)>::is_noexcept))
326 template <typename S, typename R>
327 BOOST_ASIO_CONSTEXPR typename enable_if<
328 call_traits<S&, void(const R&)>::overload == call_free,
329 typename call_traits<S&, void(const R&)>::result_type
331 operator()(S& s, const R& r) const
332 BOOST_ASIO_NOEXCEPT_IF((
333 call_traits<S&, void(const R&)>::is_noexcept))
338 template <typename S, typename R>
339 BOOST_ASIO_CONSTEXPR typename enable_if<
340 call_traits<const S&, void(const R&)>::overload == call_free,
341 typename call_traits<const S&, void(const R&)>::result_type
343 operator()(const S& s, const R& r) const
344 BOOST_ASIO_NOEXCEPT_IF((
345 call_traits<const S&, void(const R&)>::is_noexcept))
350 template <typename S, typename R>
351 BOOST_ASIO_CONSTEXPR typename enable_if<
352 call_traits<S&, void(const R&)>::overload == adapter,
353 typename call_traits<S&, void(const R&)>::result_type
355 operator()(S& s, const R& r) const
356 BOOST_ASIO_NOEXCEPT_IF((
357 call_traits<S&, void(const R&)>::is_noexcept))
359 boost::asio::execution::start(
360 (new boost::asio::execution::detail::submit_receiver<
361 S&, const R&>(s, r))->state_);
364 template <typename S, typename R>
365 BOOST_ASIO_CONSTEXPR typename enable_if<
366 call_traits<const S&, void(const R&)>::overload == adapter,
367 typename call_traits<const S&, void(const R&)>::result_type
369 operator()(const S& s, const R& r) const
370 BOOST_ASIO_NOEXCEPT_IF((
371 call_traits<const S&, void(const R&)>::is_noexcept))
373 boost::asio::execution::start(
374 (new boost::asio::execution::detail::submit_receiver<
375 const S&, const R&>(s, r))->state_);
377 #endif // defined(BOOST_ASIO_HAS_MOVE)
380 template <typename T = impl>
381 struct static_instance
383 static const T instance;
386 template <typename T>
387 const T static_instance<T>::instance = {};
389 } // namespace asio_execution_submit_fn
392 namespace execution {
395 static BOOST_ASIO_CONSTEXPR const asio_execution_submit_fn::impl&
396 submit = asio_execution_submit_fn::static_instance<>::instance;
400 template <typename S, typename R>
402 integral_constant<bool,
403 asio_execution_submit_fn::call_traits<S, void(R)>::overload !=
404 asio_execution_submit_fn::ill_formed>
408 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
410 template <typename S, typename R>
411 constexpr bool can_submit_v = can_submit<S, R>::value;
413 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
415 template <typename S, typename R>
416 struct is_nothrow_submit :
417 integral_constant<bool,
418 asio_execution_submit_fn::call_traits<S, void(R)>::is_noexcept>
422 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
424 template <typename S, typename R>
425 constexpr bool is_nothrow_submit_v
426 = is_nothrow_submit<S, R>::value;
428 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
430 template <typename S, typename R>
433 typedef typename asio_execution_submit_fn::call_traits<
434 S, void(R)>::result_type type;
439 template <typename S, typename R>
440 void submit_helper(BOOST_ASIO_MOVE_ARG(S) s, BOOST_ASIO_MOVE_ARG(R) r)
442 execution::submit(BOOST_ASIO_MOVE_CAST(S)(s), BOOST_ASIO_MOVE_CAST(R)(r));
445 } // namespace detail
446 } // namespace execution
450 #endif // defined(GENERATING_DOCUMENTATION)
452 #include <boost/asio/detail/pop_options.hpp>
454 #endif // BOOST_ASIO_EXECUTION_SUBMIT_HPP