• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // execution/schedule.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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>
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     (
103       schedule_member<S>::is_valid
104     )
105   >::type> :
106   schedule_member<S>
107 {
108   BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);
109 };
110 
111 template <typename S>
112 struct call_traits<S,
113   typename enable_if<
114     (
115       !schedule_member<S>::is_valid
116       &&
117       schedule_free<S>::is_valid
118     )
119   >::type> :
120   schedule_free<S>
121 {
122   BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);
123 };
124 
125 template <typename S>
126 struct call_traits<S,
127   typename enable_if<
128     (
129       !schedule_member<S>::is_valid
130       &&
131       !schedule_free<S>::is_valid
132       &&
133       is_executor<typename decay<S>::type>::value
134     )
135   >::type>
136 {
137   BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);
138   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
139 
140 #if defined(BOOST_ASIO_HAS_MOVE)
141   typedef BOOST_ASIO_MOVE_ARG(S) result_type;
142 #else // defined(BOOST_ASIO_HAS_MOVE)
143   typedef BOOST_ASIO_MOVE_ARG(typename decay<S>::type) result_type;
144 #endif // defined(BOOST_ASIO_HAS_MOVE)
145 };
146 
147 struct impl
148 {
149   template <typename S>
150   BOOST_ASIO_CONSTEXPR typename enable_if<
151     call_traits<S>::overload == identity,
152     typename call_traits<S>::result_type
153   >::type
operator ()asio_execution_schedule_fn::impl154   operator()(BOOST_ASIO_MOVE_ARG(S) s) const
155     BOOST_ASIO_NOEXCEPT_IF((
156       call_traits<S>::is_noexcept))
157   {
158     return BOOST_ASIO_MOVE_CAST(S)(s);
159   }
160 
161 #if defined(BOOST_ASIO_HAS_MOVE)
162   template <typename S>
163   BOOST_ASIO_CONSTEXPR typename enable_if<
164     call_traits<S>::overload == call_member,
165     typename call_traits<S>::result_type
166   >::type
operator ()asio_execution_schedule_fn::impl167   operator()(S&& s) const
168     BOOST_ASIO_NOEXCEPT_IF((
169       call_traits<S>::is_noexcept))
170   {
171     return BOOST_ASIO_MOVE_CAST(S)(s).schedule();
172   }
173 
174   template <typename S>
175   BOOST_ASIO_CONSTEXPR typename enable_if<
176     call_traits<S>::overload == call_free,
177     typename call_traits<S>::result_type
178   >::type
operator ()asio_execution_schedule_fn::impl179   operator()(S&& s) const
180     BOOST_ASIO_NOEXCEPT_IF((
181       call_traits<S>::is_noexcept))
182   {
183     return schedule(BOOST_ASIO_MOVE_CAST(S)(s));
184   }
185 #else // defined(BOOST_ASIO_HAS_MOVE)
186   template <typename S>
187   BOOST_ASIO_CONSTEXPR typename enable_if<
188     call_traits<S&>::overload == call_member,
189     typename call_traits<S&>::result_type
190   >::type
operator ()asio_execution_schedule_fn::impl191   operator()(S& s) const
192     BOOST_ASIO_NOEXCEPT_IF((
193       call_traits<S&>::is_noexcept))
194   {
195     return s.schedule();
196   }
197 
198   template <typename S>
199   BOOST_ASIO_CONSTEXPR typename enable_if<
200     call_traits<const S&>::overload == call_member,
201     typename call_traits<const S&>::result_type
202   >::type
operator ()asio_execution_schedule_fn::impl203   operator()(const S& s) const
204     BOOST_ASIO_NOEXCEPT_IF((
205       call_traits<const S&>::is_noexcept))
206   {
207     return s.schedule();
208   }
209 
210   template <typename S>
211   BOOST_ASIO_CONSTEXPR typename enable_if<
212     call_traits<S&>::overload == call_free,
213     typename call_traits<S&>::result_type
214   >::type
operator ()asio_execution_schedule_fn::impl215   operator()(S& s) const
216     BOOST_ASIO_NOEXCEPT_IF((
217       call_traits<S&>::is_noexcept))
218   {
219     return schedule(s);
220   }
221 
222   template <typename S>
223   BOOST_ASIO_CONSTEXPR typename enable_if<
224     call_traits<const S&>::overload == call_free,
225     typename call_traits<const S&>::result_type
226   >::type
operator ()asio_execution_schedule_fn::impl227   operator()(const S& s) const
228     BOOST_ASIO_NOEXCEPT_IF((
229       call_traits<const S&>::is_noexcept))
230   {
231     return schedule(s);
232   }
233 #endif // defined(BOOST_ASIO_HAS_MOVE)
234 };
235 
236 template <typename T = impl>
237 struct static_instance
238 {
239   static const T instance;
240 };
241 
242 template <typename T>
243 const T static_instance<T>::instance = {};
244 
245 } // namespace asio_execution_schedule_fn
246 namespace boost {
247 namespace asio {
248 namespace execution {
249 namespace {
250 
251 static BOOST_ASIO_CONSTEXPR const asio_execution_schedule_fn::impl&
252   schedule = asio_execution_schedule_fn::static_instance<>::instance;
253 
254 } // namespace
255 
256 template <typename S>
257 struct can_schedule :
258   integral_constant<bool,
259     asio_execution_schedule_fn::call_traits<S>::overload !=
260       asio_execution_schedule_fn::ill_formed>
261 {
262 };
263 
264 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
265 
266 template <typename S>
267 constexpr bool can_schedule_v = can_schedule<S>::value;
268 
269 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
270 
271 template <typename S>
272 struct is_nothrow_schedule :
273   integral_constant<bool,
274     asio_execution_schedule_fn::call_traits<S>::is_noexcept>
275 {
276 };
277 
278 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
279 
280 template <typename S>
281 constexpr bool is_nothrow_schedule_v
282   = is_nothrow_schedule<S>::value;
283 
284 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
285 
286 } // namespace execution
287 } // namespace asio
288 } // namespace boost
289 
290 #endif // defined(GENERATING_DOCUMENTATION)
291 
292 #include <boost/asio/detail/pop_options.hpp>
293 
294 #endif // BOOST_ASIO_EXECUTION_SCHEDULE_HPP
295