1 //
2 // execution/schedule.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 
11 #ifndef BOOST_ASIO_EXECUTION_SCHEDULE_HPP
12 #define BOOST_ASIO_EXECUTION_SCHEDULE_HPP
13 
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17 
18 #include <boost/asio/detail/config.hpp>
19 #include <boost/asio/detail/type_traits.hpp>
20 #include <boost/asio/execution/executor.hpp>
21 #include <boost/asio/traits/schedule_member.hpp>
22 #include <boost/asio/traits/schedule_free.hpp>
23 
24 #include <boost/asio/detail/push_options.hpp>
25 
26 #if defined(GENERATING_DOCUMENTATION)
27 
28 namespace boost {
29 namespace asio {
30 namespace execution {
31 
32 /// A customisation point that is used to obtain a sender from a scheduler.
33 /**
34  * The name <tt>execution::schedule</tt> denotes a customisation point object.
35  * For some subexpression <tt>s</tt>, let <tt>S</tt> be a type such that
36  * <tt>decltype((s))</tt> is <tt>S</tt>. The expression
37  * <tt>execution::schedule(s)</tt> is expression-equivalent to:
38  *
39  * @li <tt>s.schedule()</tt>, if that expression is valid and its type models
40  *   <tt>sender</tt>.
41  *
42  * @li Otherwise, <tt>schedule(s)</tt>, if that expression is valid and its
43  *   type models <tt>sender</tt> with overload resolution performed in a context
44  *   that includes the declaration <tt>void schedule();</tt> and that does not
45  *   include a declaration of <tt>execution::schedule</tt>.
46  *
47  * @li Otherwise, <tt>S</tt> if <tt>S</tt> satisfies <tt>executor</tt>.
48  *
49  * @li Otherwise, <tt>execution::schedule(s)</tt> is ill-formed.
50  */
51 inline constexpr unspecified schedule = unspecified;
52 
53 /// A type trait that determines whether a @c schedule expression is
54 /// well-formed.
55 /**
56  * Class template @c can_schedule is a trait that is derived from @c true_type
57  * if the expression <tt>execution::schedule(std::declval<S>())</tt> is well
58  * formed; otherwise @c false_type.
59  */
60 template <typename S>
61 struct can_schedule :
62   integral_constant<bool, automatically_determined>
63 {
64 };
65 
66 } // namespace execution
67 } // namespace asio
68 } // namespace boost
69 
70 #else // defined(GENERATING_DOCUMENTATION)
71 
72 namespace asio_execution_schedule_fn {
73 
74 using boost::asio::decay;
75 using boost::asio::declval;
76 using boost::asio::enable_if;
77 using boost::asio::execution::is_executor;
78 using boost::asio::traits::schedule_free;
79 using boost::asio::traits::schedule_member;
80 
81 void schedule();
82 
83 enum overload_type
84 {
85   identity,
86   call_member,
87   call_free,
88   ill_formed
89 };
90 
91 template <typename S, typename = void, typename = void, typename = void>
92 struct call_traits
93 {
94   BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);
95   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
96   typedef void result_type;
97 };
98 
99 template <typename S>
100 struct call_traits<S,
101   typename enable_if<
102     schedule_member<S>::is_valid
103   >::type> :
104   schedule_member<S>
105 {
106   BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);
107 };
108 
109 template <typename S>
110 struct call_traits<S,
111   typename enable_if<
112     !schedule_member<S>::is_valid
113   >::type,
114   typename enable_if<
115     schedule_free<S>::is_valid
116   >::type> :
117   schedule_free<S>
118 {
119   BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);
120 };
121 
122 template <typename S>
123 struct call_traits<S,
124   typename enable_if<
125     !schedule_member<S>::is_valid
126   >::type,
127   typename enable_if<
128     !schedule_free<S>::is_valid
129   >::type,
130   typename enable_if<
131     is_executor<typename decay<S>::type>::value
132   >::type>
133 {
134   BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);
135   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
136 
137 #if defined(BOOST_ASIO_HAS_MOVE)
138   typedef BOOST_ASIO_MOVE_ARG(S) result_type;
139 #else // defined(BOOST_ASIO_HAS_MOVE)
140   typedef BOOST_ASIO_MOVE_ARG(typename decay<S>::type) result_type;
141 #endif // defined(BOOST_ASIO_HAS_MOVE)
142 };
143 
144 struct impl
145 {
146   template <typename S>
147   BOOST_ASIO_CONSTEXPR typename enable_if<
148     call_traits<S>::overload == identity,
149     typename call_traits<S>::result_type
150   >::type
operator ()asio_execution_schedule_fn::impl151   operator()(BOOST_ASIO_MOVE_ARG(S) s) const
152     BOOST_ASIO_NOEXCEPT_IF((
153       call_traits<S>::is_noexcept))
154   {
155     return BOOST_ASIO_MOVE_CAST(S)(s);
156   }
157 
158 #if defined(BOOST_ASIO_HAS_MOVE)
159   template <typename S>
160   BOOST_ASIO_CONSTEXPR typename enable_if<
161     call_traits<S>::overload == call_member,
162     typename call_traits<S>::result_type
163   >::type
operator ()asio_execution_schedule_fn::impl164   operator()(S&& s) const
165     BOOST_ASIO_NOEXCEPT_IF((
166       call_traits<S>::is_noexcept))
167   {
168     return BOOST_ASIO_MOVE_CAST(S)(s).schedule();
169   }
170 
171   template <typename S>
172   BOOST_ASIO_CONSTEXPR typename enable_if<
173     call_traits<S>::overload == call_free,
174     typename call_traits<S>::result_type
175   >::type
operator ()asio_execution_schedule_fn::impl176   operator()(S&& s) const
177     BOOST_ASIO_NOEXCEPT_IF((
178       call_traits<S>::is_noexcept))
179   {
180     return schedule(BOOST_ASIO_MOVE_CAST(S)(s));
181   }
182 #else // defined(BOOST_ASIO_HAS_MOVE)
183   template <typename S>
184   BOOST_ASIO_CONSTEXPR typename enable_if<
185     call_traits<S&>::overload == call_member,
186     typename call_traits<S&>::result_type
187   >::type
operator ()asio_execution_schedule_fn::impl188   operator()(S& s) const
189     BOOST_ASIO_NOEXCEPT_IF((
190       call_traits<S&>::is_noexcept))
191   {
192     return s.schedule();
193   }
194 
195   template <typename S>
196   BOOST_ASIO_CONSTEXPR typename enable_if<
197     call_traits<const S&>::overload == call_member,
198     typename call_traits<const S&>::result_type
199   >::type
operator ()asio_execution_schedule_fn::impl200   operator()(const S& s) const
201     BOOST_ASIO_NOEXCEPT_IF((
202       call_traits<const S&>::is_noexcept))
203   {
204     return s.schedule();
205   }
206 
207   template <typename S>
208   BOOST_ASIO_CONSTEXPR typename enable_if<
209     call_traits<S&>::overload == call_free,
210     typename call_traits<S&>::result_type
211   >::type
operator ()asio_execution_schedule_fn::impl212   operator()(S& s) const
213     BOOST_ASIO_NOEXCEPT_IF((
214       call_traits<S&>::is_noexcept))
215   {
216     return schedule(s);
217   }
218 
219   template <typename S>
220   BOOST_ASIO_CONSTEXPR typename enable_if<
221     call_traits<const S&>::overload == call_free,
222     typename call_traits<const S&>::result_type
223   >::type
operator ()asio_execution_schedule_fn::impl224   operator()(const S& s) const
225     BOOST_ASIO_NOEXCEPT_IF((
226       call_traits<const S&>::is_noexcept))
227   {
228     return schedule(s);
229   }
230 #endif // defined(BOOST_ASIO_HAS_MOVE)
231 };
232 
233 template <typename T = impl>
234 struct static_instance
235 {
236   static const T instance;
237 };
238 
239 template <typename T>
240 const T static_instance<T>::instance = {};
241 
242 } // namespace asio_execution_schedule_fn
243 namespace boost {
244 namespace asio {
245 namespace execution {
246 namespace {
247 
248 static BOOST_ASIO_CONSTEXPR const asio_execution_schedule_fn::impl&
249   schedule = asio_execution_schedule_fn::static_instance<>::instance;
250 
251 } // namespace
252 
253 template <typename S>
254 struct can_schedule :
255   integral_constant<bool,
256     asio_execution_schedule_fn::call_traits<S>::overload !=
257       asio_execution_schedule_fn::ill_formed>
258 {
259 };
260 
261 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
262 
263 template <typename S>
264 constexpr bool can_schedule_v = can_schedule<S>::value;
265 
266 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
267 
268 template <typename S>
269 struct is_nothrow_schedule :
270   integral_constant<bool,
271     asio_execution_schedule_fn::call_traits<S>::is_noexcept>
272 {
273 };
274 
275 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
276 
277 template <typename S>
278 constexpr bool is_nothrow_schedule_v
279   = is_nothrow_schedule<S>::value;
280 
281 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
282 
283 } // namespace execution
284 } // namespace asio
285 } // namespace boost
286 
287 #endif // defined(GENERATING_DOCUMENTATION)
288 
289 #include <boost/asio/detail/pop_options.hpp>
290 
291 #endif // BOOST_ASIO_EXECUTION_SCHEDULE_HPP
292