1 //
2 // execution/mapping.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_MAPPING_HPP
12 #define BOOST_ASIO_EXECUTION_MAPPING_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/execution/scheduler.hpp>
22 #include <boost/asio/execution/sender.hpp>
23 #include <boost/asio/is_applicable_property.hpp>
24 #include <boost/asio/query.hpp>
25 #include <boost/asio/traits/query_free.hpp>
26 #include <boost/asio/traits/query_member.hpp>
27 #include <boost/asio/traits/query_static_constexpr_member.hpp>
28 #include <boost/asio/traits/static_query.hpp>
29 #include <boost/asio/traits/static_require.hpp>
30 
31 #include <boost/asio/detail/push_options.hpp>
32 
33 namespace boost {
34 namespace asio {
35 
36 #if defined(GENERATING_DOCUMENTATION)
37 
38 namespace execution {
39 
40 /// A property to describe what guarantees an executor makes about the mapping
41 /// of execution agents on to threads of execution.
42 struct mapping_t
43 {
44   /// The mapping_t property applies to executors, senders, and schedulers.
45   template <typename T>
46   static constexpr bool is_applicable_property_v =
47     is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
48 
49   /// The top-level mapping_t property cannot be required.
50   static constexpr bool is_requirable = false;
51 
52   /// The top-level mapping_t property cannot be preferred.
53   static constexpr bool is_preferable = false;
54 
55   /// The type returned by queries against an @c any_executor.
56   typedef mapping_t polymorphic_query_result_type;
57 
58   /// A sub-property that indicates that execution agents are mapped on to
59   /// threads of execution.
60   struct thread_t
61   {
62     /// The mapping_t::thread_t property applies to executors, senders, and
63     /// schedulers.
64     template <typename T>
65     static constexpr bool is_applicable_property_v =
66       is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
67 
68     /// The mapping_t::thread_t property can be required.
69     static constexpr bool is_requirable = true;
70 
71     /// The mapping_t::thread_t property can be preferred.
72     static constexpr bool is_preferable = true;
73 
74     /// The type returned by queries against an @c any_executor.
75     typedef mapping_t polymorphic_query_result_type;
76 
77     /// Default constructor.
78     constexpr thread_t();
79 
80     /// Get the value associated with a property object.
81     /**
82      * @returns thread_t();
83      */
84     static constexpr mapping_t value();
85   };
86 
87   /// A sub-property that indicates that execution agents are mapped on to
88   /// new threads of execution.
89   struct new_thread_t
90   {
91     /// The mapping_t::new_thread_t property applies to executors, senders, and
92     /// schedulers.
93     template <typename T>
94     static constexpr bool is_applicable_property_v =
95       is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
96 
97     /// The mapping_t::new_thread_t property can be required.
98     static constexpr bool is_requirable = true;
99 
100     /// The mapping_t::new_thread_t property can be preferred.
101     static constexpr bool is_preferable = true;
102 
103     /// The type returned by queries against an @c any_executor.
104     typedef mapping_t polymorphic_query_result_type;
105 
106     /// Default constructor.
107     constexpr new_thread_t();
108 
109     /// Get the value associated with a property object.
110     /**
111      * @returns new_thread_t();
112      */
113     static constexpr mapping_t value();
114   };
115 
116   /// A sub-property that indicates that the mapping of execution agents is
117   /// implementation-defined.
118   struct other_t
119   {
120     /// The mapping_t::other_t property applies to executors, senders, and
121     /// schedulers.
122     template <typename T>
123     static constexpr bool is_applicable_property_v =
124       is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
125 
126     /// The mapping_t::other_t property can be required.
127     static constexpr bool is_requirable = true;
128 
129     /// The mapping_t::other_t property can be preferred.
130     static constexpr bool is_preferable = true;
131 
132     /// The type returned by queries against an @c any_executor.
133     typedef mapping_t polymorphic_query_result_type;
134 
135     /// Default constructor.
136     constexpr other_t();
137 
138     /// Get the value associated with a property object.
139     /**
140      * @returns other_t();
141      */
142     static constexpr mapping_t value();
143   };
144 
145   /// A special value used for accessing the mapping_t::thread_t property.
146   static constexpr thread_t thread;
147 
148   /// A special value used for accessing the mapping_t::new_thread_t property.
149   static constexpr new_thread_t new_thread;
150 
151   /// A special value used for accessing the mapping_t::other_t property.
152   static constexpr other_t other;
153 
154   /// Default constructor.
155   constexpr mapping_t();
156 
157   /// Construct from a sub-property value.
158   constexpr mapping_t(thread_t);
159 
160   /// Construct from a sub-property value.
161   constexpr mapping_t(new_thread_t);
162 
163   /// Construct from a sub-property value.
164   constexpr mapping_t(other_t);
165 
166   /// Compare property values for equality.
167   friend constexpr bool operator==(
168       const mapping_t& a, const mapping_t& b) noexcept;
169 
170   /// Compare property values for inequality.
171   friend constexpr bool operator!=(
172       const mapping_t& a, const mapping_t& b) noexcept;
173 };
174 
175 /// A special value used for accessing the mapping_t property.
176 constexpr mapping_t mapping;
177 
178 } // namespace execution
179 
180 #else // defined(GENERATING_DOCUMENTATION)
181 
182 namespace execution {
183 namespace detail {
184 namespace mapping {
185 
186 template <int I> struct thread_t;
187 template <int I> struct new_thread_t;
188 template <int I> struct other_t;
189 
190 } // namespace mapping
191 
192 template <int I = 0>
193 struct mapping_t
194 {
195 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
196   template <typename T>
197   BOOST_ASIO_STATIC_CONSTEXPR(bool,
198     is_applicable_property_v = is_executor<T>::value
199       || is_sender<T>::value || is_scheduler<T>::value);
200 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
201 
202   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);
203   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);
204   typedef mapping_t polymorphic_query_result_type;
205 
206   typedef detail::mapping::thread_t<I> thread_t;
207   typedef detail::mapping::new_thread_t<I> new_thread_t;
208   typedef detail::mapping::other_t<I> other_t;
209 
210   BOOST_ASIO_CONSTEXPR mapping_t()
211     : value_(-1)
212   {
213   }
214 
215   BOOST_ASIO_CONSTEXPR mapping_t(thread_t)
216     : value_(0)
217   {
218   }
219 
220   BOOST_ASIO_CONSTEXPR mapping_t(new_thread_t)
221     : value_(1)
222   {
223   }
224 
225   BOOST_ASIO_CONSTEXPR mapping_t(other_t)
226     : value_(2)
227   {
228   }
229 
230 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
231   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
232   template <typename T>
233   static BOOST_ASIO_CONSTEXPR
234   typename traits::query_static_constexpr_member<T, mapping_t>::result_type
235   static_query()
236     BOOST_ASIO_NOEXCEPT_IF((
237       traits::query_static_constexpr_member<T, mapping_t>::is_noexcept))
238   {
239     return traits::query_static_constexpr_member<T, mapping_t>::value();
240   }
241 
242   template <typename T>
243   static BOOST_ASIO_CONSTEXPR
244   typename traits::static_query<T, thread_t>::result_type
245   static_query(
246       typename enable_if<
247         !traits::query_static_constexpr_member<T, mapping_t>::is_valid
248           && !traits::query_member<T, mapping_t>::is_valid
249           && traits::static_query<T, thread_t>::is_valid
250       >::type* = 0) BOOST_ASIO_NOEXCEPT
251   {
252     return traits::static_query<T, thread_t>::value();
253   }
254 
255   template <typename T>
256   static BOOST_ASIO_CONSTEXPR
257   typename traits::static_query<T, new_thread_t>::result_type
258   static_query(
259       typename enable_if<
260         !traits::query_static_constexpr_member<T, mapping_t>::is_valid
261           && !traits::query_member<T, mapping_t>::is_valid
262           && !traits::static_query<T, thread_t>::is_valid
263           && traits::static_query<T, new_thread_t>::is_valid
264       >::type* = 0) BOOST_ASIO_NOEXCEPT
265   {
266     return traits::static_query<T, new_thread_t>::value();
267   }
268 
269   template <typename T>
270   static BOOST_ASIO_CONSTEXPR
271   typename traits::static_query<T, other_t>::result_type
272   static_query(
273       typename enable_if<
274         !traits::query_static_constexpr_member<T, mapping_t>::is_valid
275           && !traits::query_member<T, mapping_t>::is_valid
276           && !traits::static_query<T, thread_t>::is_valid
277           && !traits::static_query<T, new_thread_t>::is_valid
278           && traits::static_query<T, other_t>::is_valid
279       >::type* = 0) BOOST_ASIO_NOEXCEPT
280   {
281     return traits::static_query<T, other_t>::value();
282   }
283 
284   template <typename E, typename T = decltype(mapping_t::static_query<E>())>
285   static BOOST_ASIO_CONSTEXPR const T static_query_v
286     = mapping_t::static_query<E>();
287 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
288        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
289 
290   friend BOOST_ASIO_CONSTEXPR bool operator==(
291       const mapping_t& a, const mapping_t& b)
292   {
293     return a.value_ == b.value_;
294   }
295 
296   friend BOOST_ASIO_CONSTEXPR bool operator!=(
297       const mapping_t& a, const mapping_t& b)
298   {
299     return a.value_ != b.value_;
300   }
301 
302   struct convertible_from_mapping_t
303   {
304     BOOST_ASIO_CONSTEXPR convertible_from_mapping_t(mapping_t) {}
305   };
306 
307   template <typename Executor>
308   friend BOOST_ASIO_CONSTEXPR mapping_t query(
309       const Executor& ex, convertible_from_mapping_t,
310       typename enable_if<
311         can_query<const Executor&, thread_t>::value
312       >::type* = 0)
313 #if !defined(__clang__) // Clang crashes if noexcept is used here.
314 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
315     BOOST_ASIO_NOEXCEPT_IF((
316       is_nothrow_query<const Executor&, mapping_t<>::thread_t>::value))
317 #else // defined(BOOST_ASIO_MSVC)
318     BOOST_ASIO_NOEXCEPT_IF((
319       is_nothrow_query<const Executor&, thread_t>::value))
320 #endif // defined(BOOST_ASIO_MSVC)
321 #endif // !defined(__clang__)
322   {
323     return boost::asio::query(ex, thread_t());
324   }
325 
326   template <typename Executor>
327   friend BOOST_ASIO_CONSTEXPR mapping_t query(
328       const Executor& ex, convertible_from_mapping_t,
329       typename enable_if<
330         !can_query<const Executor&, thread_t>::value
331           && can_query<const Executor&, new_thread_t>::value
332       >::type* = 0)
333 #if !defined(__clang__) // Clang crashes if noexcept is used here.
334 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
335     BOOST_ASIO_NOEXCEPT_IF((
336       is_nothrow_query<const Executor&, mapping_t<>::new_thread_t>::value))
337 #else // defined(BOOST_ASIO_MSVC)
338     BOOST_ASIO_NOEXCEPT_IF((
339       is_nothrow_query<const Executor&, new_thread_t>::value))
340 #endif // defined(BOOST_ASIO_MSVC)
341 #endif // !defined(__clang__)
342   {
343     return boost::asio::query(ex, new_thread_t());
344   }
345 
346   template <typename Executor>
347   friend BOOST_ASIO_CONSTEXPR mapping_t query(
348       const Executor& ex, convertible_from_mapping_t,
349       typename enable_if<
350         !can_query<const Executor&, thread_t>::value
351           && !can_query<const Executor&, new_thread_t>::value
352           && can_query<const Executor&, other_t>::value
353       >::type* = 0)
354 #if !defined(__clang__) // Clang crashes if noexcept is used here.
355 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
356     BOOST_ASIO_NOEXCEPT_IF((
357       is_nothrow_query<const Executor&, mapping_t<>::other_t>::value))
358 #else // defined(BOOST_ASIO_MSVC)
359     BOOST_ASIO_NOEXCEPT_IF((
360       is_nothrow_query<const Executor&, other_t>::value))
361 #endif // defined(BOOST_ASIO_MSVC)
362 #endif // !defined(__clang__)
363   {
364     return boost::asio::query(ex, other_t());
365   }
366 
367   BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(thread_t, thread);
368   BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(new_thread_t, new_thread);
369   BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(other_t, other);
370 
371 #if !defined(BOOST_ASIO_HAS_CONSTEXPR)
372   static const mapping_t instance;
373 #endif // !defined(BOOST_ASIO_HAS_CONSTEXPR)
374 
375 private:
376   int value_;
377 };
378 
379 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
380   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
381 template <int I> template <typename E, typename T>
382 const T mapping_t<I>::static_query_v;
383 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
384        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
385 
386 #if !defined(BOOST_ASIO_HAS_CONSTEXPR)
387 template <int I>
388 const mapping_t<I> mapping_t<I>::instance;
389 #endif
390 
391 template <int I>
392 const typename mapping_t<I>::thread_t mapping_t<I>::thread;
393 
394 template <int I>
395 const typename mapping_t<I>::new_thread_t mapping_t<I>::new_thread;
396 
397 template <int I>
398 const typename mapping_t<I>::other_t mapping_t<I>::other;
399 
400 namespace mapping {
401 
402 template <int I = 0>
403 struct thread_t
404 {
405 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
406   template <typename T>
407   BOOST_ASIO_STATIC_CONSTEXPR(bool,
408     is_applicable_property_v = is_executor<T>::value
409       || is_sender<T>::value || is_scheduler<T>::value);
410 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
411 
412   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
413   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
414   typedef mapping_t<I> polymorphic_query_result_type;
415 
416   BOOST_ASIO_CONSTEXPR thread_t()
417   {
418   }
419 
420 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
421   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
422   template <typename T>
423   static BOOST_ASIO_CONSTEXPR
424   typename traits::query_static_constexpr_member<T, thread_t>::result_type
425   static_query()
426     BOOST_ASIO_NOEXCEPT_IF((
427       traits::query_static_constexpr_member<T, thread_t>::is_noexcept))
428   {
429     return traits::query_static_constexpr_member<T, thread_t>::value();
430   }
431 
432   template <typename T>
433   static BOOST_ASIO_CONSTEXPR thread_t static_query(
434       typename enable_if<
435         !traits::query_static_constexpr_member<T, thread_t>::is_valid
436           && !traits::query_member<T, thread_t>::is_valid
437           && !traits::query_free<T, thread_t>::is_valid
438           && !can_query<T, new_thread_t<I> >::value
439           && !can_query<T, other_t<I> >::value
440       >::type* = 0) BOOST_ASIO_NOEXCEPT
441   {
442     return thread_t();
443   }
444 
445   template <typename E, typename T = decltype(thread_t::static_query<E>())>
446   static BOOST_ASIO_CONSTEXPR const T static_query_v
447     = thread_t::static_query<E>();
448 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
449        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
450 
451   static BOOST_ASIO_CONSTEXPR mapping_t<I> value()
452   {
453     return thread_t();
454   }
455 
456   friend BOOST_ASIO_CONSTEXPR bool operator==(
457       const thread_t&, const thread_t&)
458   {
459     return true;
460   }
461 
462   friend BOOST_ASIO_CONSTEXPR bool operator!=(
463       const thread_t&, const thread_t&)
464   {
465     return false;
466   }
467 };
468 
469 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
470   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
471 template <int I> template <typename E, typename T>
472 const T thread_t<I>::static_query_v;
473 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
474        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
475 
476 template <int I = 0>
477 struct new_thread_t
478 {
479 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
480   template <typename T>
481   BOOST_ASIO_STATIC_CONSTEXPR(bool,
482     is_applicable_property_v = is_executor<T>::value
483       || is_sender<T>::value || is_scheduler<T>::value);
484 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
485 
486   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
487   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
488   typedef mapping_t<I> polymorphic_query_result_type;
489 
490   BOOST_ASIO_CONSTEXPR new_thread_t()
491   {
492   }
493 
494 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
495   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
496   template <typename T>
497   static BOOST_ASIO_CONSTEXPR
498   typename traits::query_static_constexpr_member<T, new_thread_t>::result_type
499   static_query()
500     BOOST_ASIO_NOEXCEPT_IF((
501       traits::query_static_constexpr_member<T, new_thread_t>::is_noexcept))
502   {
503     return traits::query_static_constexpr_member<T, new_thread_t>::value();
504   }
505 
506   template <typename E, typename T = decltype(new_thread_t::static_query<E>())>
507   static BOOST_ASIO_CONSTEXPR const T static_query_v
508     = new_thread_t::static_query<E>();
509 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
510        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
511 
512   static BOOST_ASIO_CONSTEXPR mapping_t<I> value()
513   {
514     return new_thread_t();
515   }
516 
517   friend BOOST_ASIO_CONSTEXPR bool operator==(
518       const new_thread_t&, const new_thread_t&)
519   {
520     return true;
521   }
522 
523   friend BOOST_ASIO_CONSTEXPR bool operator!=(
524       const new_thread_t&, const new_thread_t&)
525   {
526     return false;
527   }
528 };
529 
530 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
531   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
532 template <int I> template <typename E, typename T>
533 const T new_thread_t<I>::static_query_v;
534 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
535        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
536 
537 template <int I>
538 struct other_t
539 {
540 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
541   template <typename T>
542   BOOST_ASIO_STATIC_CONSTEXPR(bool,
543     is_applicable_property_v = is_executor<T>::value
544       || is_sender<T>::value || is_scheduler<T>::value);
545 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
546 
547   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
548   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
549   typedef mapping_t<I> polymorphic_query_result_type;
550 
551   BOOST_ASIO_CONSTEXPR other_t()
552   {
553   }
554 
555 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
556   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
557   template <typename T>
558   static BOOST_ASIO_CONSTEXPR
559   typename traits::query_static_constexpr_member<T, other_t>::result_type
560   static_query()
561     BOOST_ASIO_NOEXCEPT_IF((
562       traits::query_static_constexpr_member<T, other_t>::is_noexcept))
563   {
564     return traits::query_static_constexpr_member<T, other_t>::value();
565   }
566 
567   template <typename E, typename T = decltype(other_t::static_query<E>())>
568   static BOOST_ASIO_CONSTEXPR const T static_query_v
569     = other_t::static_query<E>();
570 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
571        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
572 
573   static BOOST_ASIO_CONSTEXPR mapping_t<I> value()
574   {
575     return other_t();
576   }
577 
578   friend BOOST_ASIO_CONSTEXPR bool operator==(
579       const other_t&, const other_t&)
580   {
581     return true;
582   }
583 
584   friend BOOST_ASIO_CONSTEXPR bool operator!=(
585       const other_t&, const other_t&)
586   {
587     return false;
588   }
589 };
590 
591 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
592   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
593 template <int I> template <typename E, typename T>
594 const T other_t<I>::static_query_v;
595 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
596        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
597 
598 } // namespace mapping
599 } // namespace detail
600 
601 typedef detail::mapping_t<> mapping_t;
602 
603 #if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
604 constexpr mapping_t mapping;
605 #else // defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
606 namespace { static const mapping_t& mapping = mapping_t::instance; }
607 #endif
608 
609 } // namespace execution
610 
611 #if !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
612 
613 template <typename T>
614 struct is_applicable_property<T, execution::mapping_t>
615   : integral_constant<bool,
616       execution::is_executor<T>::value
617         || execution::is_sender<T>::value
618         || execution::is_scheduler<T>::value>
619 {
620 };
621 
622 template <typename T>
623 struct is_applicable_property<T, execution::mapping_t::thread_t>
624   : integral_constant<bool,
625       execution::is_executor<T>::value
626         || execution::is_sender<T>::value
627         || execution::is_scheduler<T>::value>
628 {
629 };
630 
631 template <typename T>
632 struct is_applicable_property<T, execution::mapping_t::new_thread_t>
633   : integral_constant<bool,
634       execution::is_executor<T>::value
635         || execution::is_sender<T>::value
636         || execution::is_scheduler<T>::value>
637 {
638 };
639 
640 template <typename T>
641 struct is_applicable_property<T, execution::mapping_t::other_t>
642   : integral_constant<bool,
643       execution::is_executor<T>::value
644         || execution::is_sender<T>::value
645         || execution::is_scheduler<T>::value>
646 {
647 };
648 
649 #endif // !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
650 
651 namespace traits {
652 
653 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
654 
655 template <typename T>
656 struct query_free_default<T, execution::mapping_t,
657   typename enable_if<
658     can_query<T, execution::mapping_t::thread_t>::value
659   >::type>
660 {
661   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
662   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
663     (is_nothrow_query<T, execution::mapping_t::thread_t>::value));
664 
665   typedef execution::mapping_t result_type;
666 };
667 
668 template <typename T>
669 struct query_free_default<T, execution::mapping_t,
670   typename enable_if<
671     !can_query<T, execution::mapping_t::thread_t>::value
672       && can_query<T, execution::mapping_t::new_thread_t>::value
673   >::type>
674 {
675   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
676   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
677     (is_nothrow_query<T, execution::mapping_t::new_thread_t>::value));
678 
679   typedef execution::mapping_t result_type;
680 };
681 
682 template <typename T>
683 struct query_free_default<T, execution::mapping_t,
684   typename enable_if<
685     !can_query<T, execution::mapping_t::thread_t>::value
686       && !can_query<T, execution::mapping_t::new_thread_t>::value
687       && can_query<T, execution::mapping_t::other_t>::value
688   >::type>
689 {
690   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
691   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
692     (is_nothrow_query<T, execution::mapping_t::other_t>::value));
693 
694   typedef execution::mapping_t result_type;
695 };
696 
697 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
698 
699 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
700   || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
701 
702 template <typename T>
703 struct static_query<T, execution::mapping_t,
704   typename enable_if<
705     traits::query_static_constexpr_member<T,
706       execution::mapping_t>::is_valid
707   >::type>
708 {
709   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
710   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
711 
712   typedef typename traits::query_static_constexpr_member<T,
713     execution::mapping_t>::result_type result_type;
714 
715   static BOOST_ASIO_CONSTEXPR result_type value()
716   {
717     return traits::query_static_constexpr_member<T,
718       execution::mapping_t>::value();
719   }
720 };
721 
722 template <typename T>
723 struct static_query<T, execution::mapping_t,
724   typename enable_if<
725     !traits::query_static_constexpr_member<T, execution::mapping_t>::is_valid
726       && !traits::query_member<T, execution::mapping_t>::is_valid
727       && traits::static_query<T, execution::mapping_t::thread_t>::is_valid
728   >::type>
729 {
730   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
731   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
732 
733   typedef typename traits::static_query<T,
734     execution::mapping_t::thread_t>::result_type result_type;
735 
736   static BOOST_ASIO_CONSTEXPR result_type value()
737   {
738     return traits::static_query<T, execution::mapping_t::thread_t>::value();
739   }
740 };
741 
742 template <typename T>
743 struct static_query<T, execution::mapping_t,
744   typename enable_if<
745     !traits::query_static_constexpr_member<T, execution::mapping_t>::is_valid
746       && !traits::query_member<T, execution::mapping_t>::is_valid
747       && !traits::static_query<T, execution::mapping_t::thread_t>::is_valid
748       && traits::static_query<T, execution::mapping_t::new_thread_t>::is_valid
749   >::type>
750 {
751   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
752   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
753 
754   typedef typename traits::static_query<T,
755     execution::mapping_t::new_thread_t>::result_type result_type;
756 
757   static BOOST_ASIO_CONSTEXPR result_type value()
758   {
759     return traits::static_query<T, execution::mapping_t::new_thread_t>::value();
760   }
761 };
762 
763 template <typename T>
764 struct static_query<T, execution::mapping_t,
765   typename enable_if<
766     !traits::query_static_constexpr_member<T, execution::mapping_t>::is_valid
767       && !traits::query_member<T, execution::mapping_t>::is_valid
768       && !traits::static_query<T, execution::mapping_t::thread_t>::is_valid
769       && !traits::static_query<T, execution::mapping_t::new_thread_t>::is_valid
770       && traits::static_query<T, execution::mapping_t::other_t>::is_valid
771   >::type>
772 {
773   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
774   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
775 
776   typedef typename traits::static_query<T,
777     execution::mapping_t::other_t>::result_type result_type;
778 
779   static BOOST_ASIO_CONSTEXPR result_type value()
780   {
781     return traits::static_query<T, execution::mapping_t::other_t>::value();
782   }
783 };
784 
785 template <typename T>
786 struct static_query<T, execution::mapping_t::thread_t,
787   typename enable_if<
788     traits::query_static_constexpr_member<T,
789       execution::mapping_t::thread_t>::is_valid
790   >::type>
791 {
792   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
793   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
794 
795   typedef typename traits::query_static_constexpr_member<T,
796     execution::mapping_t::thread_t>::result_type result_type;
797 
798   static BOOST_ASIO_CONSTEXPR result_type value()
799   {
800     return traits::query_static_constexpr_member<T,
801       execution::mapping_t::thread_t>::value();
802   }
803 };
804 
805 template <typename T>
806 struct static_query<T, execution::mapping_t::thread_t,
807   typename enable_if<
808     !traits::query_static_constexpr_member<T,
809       execution::mapping_t::thread_t>::is_valid
810       && !traits::query_member<T, execution::mapping_t::thread_t>::is_valid
811       && !traits::query_free<T, execution::mapping_t::thread_t>::is_valid
812       && !can_query<T, execution::mapping_t::new_thread_t>::value
813       && !can_query<T, execution::mapping_t::other_t>::value
814   >::type>
815 {
816   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
817   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
818 
819   typedef execution::mapping_t::thread_t result_type;
820 
821   static BOOST_ASIO_CONSTEXPR result_type value()
822   {
823     return result_type();
824   }
825 };
826 
827 template <typename T>
828 struct static_query<T, execution::mapping_t::new_thread_t,
829   typename enable_if<
830     traits::query_static_constexpr_member<T,
831       execution::mapping_t::new_thread_t>::is_valid
832   >::type>
833 {
834   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
835   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
836 
837   typedef typename traits::query_static_constexpr_member<T,
838     execution::mapping_t::new_thread_t>::result_type result_type;
839 
840   static BOOST_ASIO_CONSTEXPR result_type value()
841   {
842     return traits::query_static_constexpr_member<T,
843       execution::mapping_t::new_thread_t>::value();
844   }
845 };
846 
847 template <typename T>
848 struct static_query<T, execution::mapping_t::other_t,
849   typename enable_if<
850     traits::query_static_constexpr_member<T,
851       execution::mapping_t::other_t>::is_valid
852   >::type>
853 {
854   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
855   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
856 
857   typedef typename traits::query_static_constexpr_member<T,
858     execution::mapping_t::other_t>::result_type result_type;
859 
860   static BOOST_ASIO_CONSTEXPR result_type value()
861   {
862     return traits::query_static_constexpr_member<T,
863       execution::mapping_t::other_t>::value();
864   }
865 };
866 
867 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
868        //   || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
869 
870 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)
871 
872 template <typename T>
873 struct static_require<T, execution::mapping_t::thread_t,
874   typename enable_if<
875     static_query<T, execution::mapping_t::thread_t>::is_valid
876   >::type>
877 {
878   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
879     (is_same<typename static_query<T,
880       execution::mapping_t::thread_t>::result_type,
881         execution::mapping_t::thread_t>::value));
882 };
883 
884 template <typename T>
885 struct static_require<T, execution::mapping_t::new_thread_t,
886   typename enable_if<
887     static_query<T, execution::mapping_t::new_thread_t>::is_valid
888   >::type>
889 {
890   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
891     (is_same<typename static_query<T,
892       execution::mapping_t::new_thread_t>::result_type,
893         execution::mapping_t::new_thread_t>::value));
894 };
895 
896 template <typename T>
897 struct static_require<T, execution::mapping_t::other_t,
898   typename enable_if<
899     static_query<T, execution::mapping_t::other_t>::is_valid
900   >::type>
901 {
902   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
903     (is_same<typename static_query<T,
904       execution::mapping_t::other_t>::result_type,
905         execution::mapping_t::other_t>::value));
906 };
907 
908 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)
909 
910 } // namespace traits
911 
912 #endif // defined(GENERATING_DOCUMENTATION)
913 
914 } // namespace asio
915 } // namespace boost
916 
917 #include <boost/asio/detail/pop_options.hpp>
918 
919 #endif // BOOST_ASIO_EXECUTION_MAPPING_HPP
920