1 //
2 // execution/mapping.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_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 = (
199       is_executor<T>::value
200         || conditional<
201             is_executor<T>::value,
202             false_type,
203             is_sender<T>
204           >::type::value
205         || conditional<
206             is_executor<T>::value,
207             false_type,
208             is_scheduler<T>
209           >::type::value));
210 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
211 
212   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);
213   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);
214   typedef mapping_t polymorphic_query_result_type;
215 
216   typedef detail::mapping::thread_t<I> thread_t;
217   typedef detail::mapping::new_thread_t<I> new_thread_t;
218   typedef detail::mapping::other_t<I> other_t;
219 
220   BOOST_ASIO_CONSTEXPR mapping_t()
221     : value_(-1)
222   {
223   }
224 
225   BOOST_ASIO_CONSTEXPR mapping_t(thread_t)
226     : value_(0)
227   {
228   }
229 
230   BOOST_ASIO_CONSTEXPR mapping_t(new_thread_t)
231     : value_(1)
232   {
233   }
234 
235   BOOST_ASIO_CONSTEXPR mapping_t(other_t)
236     : value_(2)
237   {
238   }
239 
240   template <typename T>
241   struct proxy
242   {
243 #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
244     struct type
245     {
246       template <typename P>
247       auto query(BOOST_ASIO_MOVE_ARG(P) p) const
248         noexcept(
249           noexcept(
250             declval<typename conditional<true, T, P>::type>().query(
251               BOOST_ASIO_MOVE_CAST(P)(p))
252           )
253         )
254         -> decltype(
255           declval<typename conditional<true, T, P>::type>().query(
256             BOOST_ASIO_MOVE_CAST(P)(p))
257         );
258     };
259 #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
260     typedef T type;
261 #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
262   };
263 
264   template <typename T>
265   struct static_proxy
266   {
267 #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
268     struct type
269     {
270       template <typename P>
271       static constexpr auto query(BOOST_ASIO_MOVE_ARG(P) p)
272         noexcept(
273           noexcept(
274             conditional<true, T, P>::type::query(BOOST_ASIO_MOVE_CAST(P)(p))
275           )
276         )
277         -> decltype(
278           conditional<true, T, P>::type::query(BOOST_ASIO_MOVE_CAST(P)(p))
279         )
280       {
281         return T::query(BOOST_ASIO_MOVE_CAST(P)(p));
282       }
283     };
284 #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
285     typedef T type;
286 #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
287   };
288 
289   template <typename T>
290   struct query_member :
291     traits::query_member<typename proxy<T>::type, mapping_t> {};
292 
293   template <typename T>
294   struct query_static_constexpr_member :
295     traits::query_static_constexpr_member<
296       typename static_proxy<T>::type, mapping_t> {};
297 
298 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
299   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
300   template <typename T>
301   static BOOST_ASIO_CONSTEXPR
302   typename query_static_constexpr_member<T>::result_type
303   static_query()
304     BOOST_ASIO_NOEXCEPT_IF((
305       query_static_constexpr_member<T>::is_noexcept))
306   {
307     return query_static_constexpr_member<T>::value();
308   }
309 
310   template <typename T>
311   static BOOST_ASIO_CONSTEXPR
312   typename traits::static_query<T, thread_t>::result_type
313   static_query(
314       typename enable_if<
315         !query_static_constexpr_member<T>::is_valid
316       >::type* = 0,
317       typename enable_if<
318         !query_member<T>::is_valid
319       >::type* = 0,
320       typename enable_if<
321         traits::static_query<T, thread_t>::is_valid
322       >::type* = 0) BOOST_ASIO_NOEXCEPT
323   {
324     return traits::static_query<T, thread_t>::value();
325   }
326 
327   template <typename T>
328   static BOOST_ASIO_CONSTEXPR
329   typename traits::static_query<T, new_thread_t>::result_type
330   static_query(
331       typename enable_if<
332         !query_static_constexpr_member<T>::is_valid
333       >::type* = 0,
334       typename enable_if<
335         !query_member<T>::is_valid
336       >::type* = 0,
337       typename enable_if<
338         !traits::static_query<T, thread_t>::is_valid
339       >::type* = 0,
340       typename enable_if<
341         traits::static_query<T, new_thread_t>::is_valid
342       >::type* = 0) BOOST_ASIO_NOEXCEPT
343   {
344     return traits::static_query<T, new_thread_t>::value();
345   }
346 
347   template <typename T>
348   static BOOST_ASIO_CONSTEXPR
349   typename traits::static_query<T, other_t>::result_type
350   static_query(
351       typename enable_if<
352         !query_static_constexpr_member<T>::is_valid
353       >::type* = 0,
354       typename enable_if<
355         !query_member<T>::is_valid
356       >::type* = 0,
357       typename enable_if<
358         !traits::static_query<T, thread_t>::is_valid
359       >::type* = 0,
360       typename enable_if<
361         !traits::static_query<T, new_thread_t>::is_valid
362       >::type* = 0,
363       typename enable_if<
364         traits::static_query<T, other_t>::is_valid
365       >::type* = 0) BOOST_ASIO_NOEXCEPT
366   {
367     return traits::static_query<T, other_t>::value();
368   }
369 
370   template <typename E, typename T = decltype(mapping_t::static_query<E>())>
371   static BOOST_ASIO_CONSTEXPR const T static_query_v
372     = mapping_t::static_query<E>();
373 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
374        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
375 
376   friend BOOST_ASIO_CONSTEXPR bool operator==(
377       const mapping_t& a, const mapping_t& b)
378   {
379     return a.value_ == b.value_;
380   }
381 
382   friend BOOST_ASIO_CONSTEXPR bool operator!=(
383       const mapping_t& a, const mapping_t& b)
384   {
385     return a.value_ != b.value_;
386   }
387 
388   struct convertible_from_mapping_t
389   {
390     BOOST_ASIO_CONSTEXPR convertible_from_mapping_t(mapping_t) {}
391   };
392 
393   template <typename Executor>
394   friend BOOST_ASIO_CONSTEXPR mapping_t query(
395       const Executor& ex, convertible_from_mapping_t,
396       typename enable_if<
397         can_query<const Executor&, thread_t>::value
398       >::type* = 0)
399 #if !defined(__clang__) // Clang crashes if noexcept is used here.
400 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
401     BOOST_ASIO_NOEXCEPT_IF((
402       is_nothrow_query<const Executor&, mapping_t<>::thread_t>::value))
403 #else // defined(BOOST_ASIO_MSVC)
404     BOOST_ASIO_NOEXCEPT_IF((
405       is_nothrow_query<const Executor&, thread_t>::value))
406 #endif // defined(BOOST_ASIO_MSVC)
407 #endif // !defined(__clang__)
408   {
409     return boost::asio::query(ex, thread_t());
410   }
411 
412   template <typename Executor>
413   friend BOOST_ASIO_CONSTEXPR mapping_t query(
414       const Executor& ex, convertible_from_mapping_t,
415       typename enable_if<
416         !can_query<const Executor&, thread_t>::value
417       >::type* = 0,
418       typename enable_if<
419         can_query<const Executor&, new_thread_t>::value
420       >::type* = 0)
421 #if !defined(__clang__) // Clang crashes if noexcept is used here.
422 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
423     BOOST_ASIO_NOEXCEPT_IF((
424       is_nothrow_query<const Executor&, mapping_t<>::new_thread_t>::value))
425 #else // defined(BOOST_ASIO_MSVC)
426     BOOST_ASIO_NOEXCEPT_IF((
427       is_nothrow_query<const Executor&, new_thread_t>::value))
428 #endif // defined(BOOST_ASIO_MSVC)
429 #endif // !defined(__clang__)
430   {
431     return boost::asio::query(ex, new_thread_t());
432   }
433 
434   template <typename Executor>
435   friend BOOST_ASIO_CONSTEXPR mapping_t query(
436       const Executor& ex, convertible_from_mapping_t,
437       typename enable_if<
438         !can_query<const Executor&, thread_t>::value
439       >::type* = 0,
440       typename enable_if<
441         !can_query<const Executor&, new_thread_t>::value
442       >::type* = 0,
443       typename enable_if<
444         can_query<const Executor&, other_t>::value
445       >::type* = 0)
446 #if !defined(__clang__) // Clang crashes if noexcept is used here.
447 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
448     BOOST_ASIO_NOEXCEPT_IF((
449       is_nothrow_query<const Executor&, mapping_t<>::other_t>::value))
450 #else // defined(BOOST_ASIO_MSVC)
451     BOOST_ASIO_NOEXCEPT_IF((
452       is_nothrow_query<const Executor&, other_t>::value))
453 #endif // defined(BOOST_ASIO_MSVC)
454 #endif // !defined(__clang__)
455   {
456     return boost::asio::query(ex, other_t());
457   }
458 
459   BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(thread_t, thread);
460   BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(new_thread_t, new_thread);
461   BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(other_t, other);
462 
463 #if !defined(BOOST_ASIO_HAS_CONSTEXPR)
464   static const mapping_t instance;
465 #endif // !defined(BOOST_ASIO_HAS_CONSTEXPR)
466 
467 private:
468   int value_;
469 };
470 
471 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
472   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
473 template <int I> template <typename E, typename T>
474 const T mapping_t<I>::static_query_v;
475 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
476        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
477 
478 #if !defined(BOOST_ASIO_HAS_CONSTEXPR)
479 template <int I>
480 const mapping_t<I> mapping_t<I>::instance;
481 #endif
482 
483 template <int I>
484 const typename mapping_t<I>::thread_t mapping_t<I>::thread;
485 
486 template <int I>
487 const typename mapping_t<I>::new_thread_t mapping_t<I>::new_thread;
488 
489 template <int I>
490 const typename mapping_t<I>::other_t mapping_t<I>::other;
491 
492 namespace mapping {
493 
494 template <int I = 0>
495 struct thread_t
496 {
497 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
498   template <typename T>
499   BOOST_ASIO_STATIC_CONSTEXPR(bool,
500     is_applicable_property_v = (
501       is_executor<T>::value
502         || conditional<
503             is_executor<T>::value,
504             false_type,
505             is_sender<T>
506           >::type::value
507         || conditional<
508             is_executor<T>::value,
509             false_type,
510             is_scheduler<T>
511           >::type::value));
512 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
513 
514   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
515   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
516   typedef mapping_t<I> polymorphic_query_result_type;
517 
518   BOOST_ASIO_CONSTEXPR thread_t()
519   {
520   }
521 
522   template <typename T>
523   struct query_member :
524     traits::query_member<
525       typename mapping_t<I>::template proxy<T>::type, thread_t> {};
526 
527   template <typename T>
528   struct query_static_constexpr_member :
529     traits::query_static_constexpr_member<
530       typename mapping_t<I>::template static_proxy<T>::type, thread_t> {};
531 
532 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
533   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
534   template <typename T>
535   static BOOST_ASIO_CONSTEXPR
536   typename query_static_constexpr_member<T>::result_type
537   static_query()
538     BOOST_ASIO_NOEXCEPT_IF((
539       query_static_constexpr_member<T>::is_noexcept))
540   {
541     return query_static_constexpr_member<T>::value();
542   }
543 
544   template <typename T>
545   static BOOST_ASIO_CONSTEXPR thread_t static_query(
546       typename enable_if<
547         !query_static_constexpr_member<T>::is_valid
548       >::type* = 0,
549       typename enable_if<
550         !query_member<T>::is_valid
551       >::type* = 0,
552       typename enable_if<
553         !traits::query_free<T, thread_t>::is_valid
554       >::type* = 0,
555       typename enable_if<
556         !can_query<T, new_thread_t<I> >::value
557       >::type* = 0,
558       typename enable_if<
559         !can_query<T, other_t<I> >::value
560       >::type* = 0) BOOST_ASIO_NOEXCEPT
561   {
562     return thread_t();
563   }
564 
565   template <typename E, typename T = decltype(thread_t::static_query<E>())>
566   static BOOST_ASIO_CONSTEXPR const T static_query_v
567     = thread_t::static_query<E>();
568 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
569        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
570 
571   static BOOST_ASIO_CONSTEXPR mapping_t<I> value()
572   {
573     return thread_t();
574   }
575 
576   friend BOOST_ASIO_CONSTEXPR bool operator==(
577       const thread_t&, const thread_t&)
578   {
579     return true;
580   }
581 
582   friend BOOST_ASIO_CONSTEXPR bool operator!=(
583       const thread_t&, const thread_t&)
584   {
585     return false;
586   }
587 };
588 
589 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
590   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
591 template <int I> template <typename E, typename T>
592 const T thread_t<I>::static_query_v;
593 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
594        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
595 
596 template <int I = 0>
597 struct new_thread_t
598 {
599 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
600   template <typename T>
601   BOOST_ASIO_STATIC_CONSTEXPR(bool,
602     is_applicable_property_v = (
603       is_executor<T>::value
604         || conditional<
605             is_executor<T>::value,
606             false_type,
607             is_sender<T>
608           >::type::value
609         || conditional<
610             is_executor<T>::value,
611             false_type,
612             is_scheduler<T>
613           >::type::value));
614 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
615 
616   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
617   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
618   typedef mapping_t<I> polymorphic_query_result_type;
619 
620   BOOST_ASIO_CONSTEXPR new_thread_t()
621   {
622   }
623 
624   template <typename T>
625   struct query_member :
626     traits::query_member<
627       typename mapping_t<I>::template proxy<T>::type, new_thread_t> {};
628 
629   template <typename T>
630   struct query_static_constexpr_member :
631     traits::query_static_constexpr_member<
632       typename mapping_t<I>::template static_proxy<T>::type, new_thread_t> {};
633 
634 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
635   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
636   template <typename T>
637   static BOOST_ASIO_CONSTEXPR
638   typename query_static_constexpr_member<T>::result_type
639   static_query()
640     BOOST_ASIO_NOEXCEPT_IF((
641       query_static_constexpr_member<T>::is_noexcept))
642   {
643     return query_static_constexpr_member<T>::value();
644   }
645 
646   template <typename E, typename T = decltype(new_thread_t::static_query<E>())>
647   static BOOST_ASIO_CONSTEXPR const T static_query_v
648     = new_thread_t::static_query<E>();
649 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
650        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
651 
652   static BOOST_ASIO_CONSTEXPR mapping_t<I> value()
653   {
654     return new_thread_t();
655   }
656 
657   friend BOOST_ASIO_CONSTEXPR bool operator==(
658       const new_thread_t&, const new_thread_t&)
659   {
660     return true;
661   }
662 
663   friend BOOST_ASIO_CONSTEXPR bool operator!=(
664       const new_thread_t&, const new_thread_t&)
665   {
666     return false;
667   }
668 };
669 
670 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
671   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
672 template <int I> template <typename E, typename T>
673 const T new_thread_t<I>::static_query_v;
674 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
675        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
676 
677 template <int I>
678 struct other_t
679 {
680 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
681   template <typename T>
682   BOOST_ASIO_STATIC_CONSTEXPR(bool,
683     is_applicable_property_v = (
684       is_executor<T>::value
685         || conditional<
686             is_executor<T>::value,
687             false_type,
688             is_sender<T>
689           >::type::value
690         || conditional<
691             is_executor<T>::value,
692             false_type,
693             is_scheduler<T>
694           >::type::value));
695 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
696 
697   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
698   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
699   typedef mapping_t<I> polymorphic_query_result_type;
700 
701   BOOST_ASIO_CONSTEXPR other_t()
702   {
703   }
704 
705   template <typename T>
706   struct query_member :
707     traits::query_member<
708       typename mapping_t<I>::template proxy<T>::type, other_t> {};
709 
710   template <typename T>
711   struct query_static_constexpr_member :
712     traits::query_static_constexpr_member<
713       typename mapping_t<I>::template static_proxy<T>::type, other_t> {};
714 
715 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
716   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
717   template <typename T>
718   static BOOST_ASIO_CONSTEXPR
719   typename query_static_constexpr_member<T>::result_type
720   static_query()
721     BOOST_ASIO_NOEXCEPT_IF((
722       query_static_constexpr_member<T>::is_noexcept))
723   {
724     return query_static_constexpr_member<T>::value();
725   }
726 
727   template <typename E, typename T = decltype(other_t::static_query<E>())>
728   static BOOST_ASIO_CONSTEXPR const T static_query_v
729     = other_t::static_query<E>();
730 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
731        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
732 
733   static BOOST_ASIO_CONSTEXPR mapping_t<I> value()
734   {
735     return other_t();
736   }
737 
738   friend BOOST_ASIO_CONSTEXPR bool operator==(
739       const other_t&, const other_t&)
740   {
741     return true;
742   }
743 
744   friend BOOST_ASIO_CONSTEXPR bool operator!=(
745       const other_t&, const other_t&)
746   {
747     return false;
748   }
749 };
750 
751 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
752   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
753 template <int I> template <typename E, typename T>
754 const T other_t<I>::static_query_v;
755 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
756        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
757 
758 } // namespace mapping
759 } // namespace detail
760 
761 typedef detail::mapping_t<> mapping_t;
762 
763 #if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
764 constexpr mapping_t mapping;
765 #else // defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
766 namespace { static const mapping_t& mapping = mapping_t::instance; }
767 #endif
768 
769 } // namespace execution
770 
771 #if !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
772 
773 template <typename T>
774 struct is_applicable_property<T, execution::mapping_t>
775   : integral_constant<bool,
776       execution::is_executor<T>::value
777         || conditional<
778             execution::is_executor<T>::value,
779             false_type,
780             execution::is_sender<T>
781           >::type::value
782         || conditional<
783             execution::is_executor<T>::value,
784             false_type,
785             execution::is_scheduler<T>
786           >::type::value>
787 {
788 };
789 
790 template <typename T>
791 struct is_applicable_property<T, execution::mapping_t::thread_t>
792   : integral_constant<bool,
793       execution::is_executor<T>::value
794         || conditional<
795             execution::is_executor<T>::value,
796             false_type,
797             execution::is_sender<T>
798           >::type::value
799         || conditional<
800             execution::is_executor<T>::value,
801             false_type,
802             execution::is_scheduler<T>
803           >::type::value>
804 {
805 };
806 
807 template <typename T>
808 struct is_applicable_property<T, execution::mapping_t::new_thread_t>
809   : integral_constant<bool,
810       execution::is_executor<T>::value
811         || conditional<
812             execution::is_executor<T>::value,
813             false_type,
814             execution::is_sender<T>
815           >::type::value
816         || conditional<
817             execution::is_executor<T>::value,
818             false_type,
819             execution::is_scheduler<T>
820           >::type::value>
821 {
822 };
823 
824 template <typename T>
825 struct is_applicable_property<T, execution::mapping_t::other_t>
826   : integral_constant<bool,
827       execution::is_executor<T>::value
828         || conditional<
829             execution::is_executor<T>::value,
830             false_type,
831             execution::is_sender<T>
832           >::type::value
833         || conditional<
834             execution::is_executor<T>::value,
835             false_type,
836             execution::is_scheduler<T>
837           >::type::value>
838 {
839 };
840 
841 #endif // !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
842 
843 namespace traits {
844 
845 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
846 
847 template <typename T>
848 struct query_free_default<T, execution::mapping_t,
849   typename enable_if<
850     can_query<T, execution::mapping_t::thread_t>::value
851   >::type>
852 {
853   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
854   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
855     (is_nothrow_query<T, execution::mapping_t::thread_t>::value));
856 
857   typedef execution::mapping_t result_type;
858 };
859 
860 template <typename T>
861 struct query_free_default<T, execution::mapping_t,
862   typename enable_if<
863     !can_query<T, execution::mapping_t::thread_t>::value
864       && can_query<T, execution::mapping_t::new_thread_t>::value
865   >::type>
866 {
867   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
868   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
869     (is_nothrow_query<T, execution::mapping_t::new_thread_t>::value));
870 
871   typedef execution::mapping_t result_type;
872 };
873 
874 template <typename T>
875 struct query_free_default<T, execution::mapping_t,
876   typename enable_if<
877     !can_query<T, execution::mapping_t::thread_t>::value
878       && !can_query<T, execution::mapping_t::new_thread_t>::value
879       && can_query<T, execution::mapping_t::other_t>::value
880   >::type>
881 {
882   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
883   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
884     (is_nothrow_query<T, execution::mapping_t::other_t>::value));
885 
886   typedef execution::mapping_t result_type;
887 };
888 
889 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
890 
891 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
892   || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
893 
894 template <typename T>
895 struct static_query<T, execution::mapping_t,
896   typename enable_if<
897     execution::detail::mapping_t<0>::
898       query_static_constexpr_member<T>::is_valid
899   >::type>
900 {
901   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
902   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
903 
904   typedef typename execution::detail::mapping_t<0>::
905     query_static_constexpr_member<T>::result_type result_type;
906 
907   static BOOST_ASIO_CONSTEXPR result_type value()
908   {
909     return execution::detail::mapping_t<0>::
910       query_static_constexpr_member<T>::value();
911   }
912 };
913 
914 template <typename T>
915 struct static_query<T, execution::mapping_t,
916   typename enable_if<
917     !execution::detail::mapping_t<0>::
918         query_static_constexpr_member<T>::is_valid
919       && !execution::detail::mapping_t<0>::
920         query_member<T>::is_valid
921       && traits::static_query<T, execution::mapping_t::thread_t>::is_valid
922   >::type>
923 {
924   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
925   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
926 
927   typedef typename traits::static_query<T,
928     execution::mapping_t::thread_t>::result_type result_type;
929 
930   static BOOST_ASIO_CONSTEXPR result_type value()
931   {
932     return traits::static_query<T, execution::mapping_t::thread_t>::value();
933   }
934 };
935 
936 template <typename T>
937 struct static_query<T, execution::mapping_t,
938   typename enable_if<
939     !execution::detail::mapping_t<0>::
940         query_static_constexpr_member<T>::is_valid
941       && !execution::detail::mapping_t<0>::
942         query_member<T>::is_valid
943       && !traits::static_query<T, execution::mapping_t::thread_t>::is_valid
944       && traits::static_query<T, execution::mapping_t::new_thread_t>::is_valid
945   >::type>
946 {
947   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
948   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
949 
950   typedef typename traits::static_query<T,
951     execution::mapping_t::new_thread_t>::result_type result_type;
952 
953   static BOOST_ASIO_CONSTEXPR result_type value()
954   {
955     return traits::static_query<T, execution::mapping_t::new_thread_t>::value();
956   }
957 };
958 
959 template <typename T>
960 struct static_query<T, execution::mapping_t,
961   typename enable_if<
962     !execution::detail::mapping_t<0>::
963         query_static_constexpr_member<T>::is_valid
964       && !execution::detail::mapping_t<0>::
965         query_member<T>::is_valid
966       && !traits::static_query<T, execution::mapping_t::thread_t>::is_valid
967       && !traits::static_query<T, execution::mapping_t::new_thread_t>::is_valid
968       && traits::static_query<T, execution::mapping_t::other_t>::is_valid
969   >::type>
970 {
971   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
972   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
973 
974   typedef typename traits::static_query<T,
975     execution::mapping_t::other_t>::result_type result_type;
976 
977   static BOOST_ASIO_CONSTEXPR result_type value()
978   {
979     return traits::static_query<T, execution::mapping_t::other_t>::value();
980   }
981 };
982 
983 template <typename T>
984 struct static_query<T, execution::mapping_t::thread_t,
985   typename enable_if<
986     execution::detail::mapping::thread_t<0>::
987       query_static_constexpr_member<T>::is_valid
988   >::type>
989 {
990   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
991   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
992 
993   typedef typename execution::detail::mapping::thread_t<0>::
994     query_static_constexpr_member<T>::result_type result_type;
995 
996   static BOOST_ASIO_CONSTEXPR result_type value()
997   {
998     return execution::detail::mapping::thread_t<0>::
999       query_static_constexpr_member<T>::value();
1000   }
1001 };
1002 
1003 template <typename T>
1004 struct static_query<T, execution::mapping_t::thread_t,
1005   typename enable_if<
1006     !execution::detail::mapping::thread_t<0>::
1007         query_static_constexpr_member<T>::is_valid
1008       && !execution::detail::mapping::thread_t<0>::
1009         query_member<T>::is_valid
1010       && !traits::query_free<T, execution::mapping_t::thread_t>::is_valid
1011       && !can_query<T, execution::mapping_t::new_thread_t>::value
1012       && !can_query<T, execution::mapping_t::other_t>::value
1013   >::type>
1014 {
1015   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
1016   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
1017 
1018   typedef execution::mapping_t::thread_t result_type;
1019 
1020   static BOOST_ASIO_CONSTEXPR result_type value()
1021   {
1022     return result_type();
1023   }
1024 };
1025 
1026 template <typename T>
1027 struct static_query<T, execution::mapping_t::new_thread_t,
1028   typename enable_if<
1029     execution::detail::mapping::new_thread_t<0>::
1030       query_static_constexpr_member<T>::is_valid
1031   >::type>
1032 {
1033   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
1034   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
1035 
1036   typedef typename execution::detail::mapping::new_thread_t<0>::
1037     query_static_constexpr_member<T>::result_type result_type;
1038 
1039   static BOOST_ASIO_CONSTEXPR result_type value()
1040   {
1041     return execution::detail::mapping::new_thread_t<0>::
1042       query_static_constexpr_member<T>::value();
1043   }
1044 };
1045 
1046 template <typename T>
1047 struct static_query<T, execution::mapping_t::other_t,
1048   typename enable_if<
1049     execution::detail::mapping::other_t<0>::
1050       query_static_constexpr_member<T>::is_valid
1051   >::type>
1052 {
1053   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
1054   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
1055 
1056   typedef typename execution::detail::mapping::other_t<0>::
1057     query_static_constexpr_member<T>::result_type result_type;
1058 
1059   static BOOST_ASIO_CONSTEXPR result_type value()
1060   {
1061     return execution::detail::mapping::other_t<0>::
1062       query_static_constexpr_member<T>::value();
1063   }
1064 };
1065 
1066 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
1067        //   || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
1068 
1069 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)
1070 
1071 template <typename T>
1072 struct static_require<T, execution::mapping_t::thread_t,
1073   typename enable_if<
1074     static_query<T, execution::mapping_t::thread_t>::is_valid
1075   >::type>
1076 {
1077   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
1078     (is_same<typename static_query<T,
1079       execution::mapping_t::thread_t>::result_type,
1080         execution::mapping_t::thread_t>::value));
1081 };
1082 
1083 template <typename T>
1084 struct static_require<T, execution::mapping_t::new_thread_t,
1085   typename enable_if<
1086     static_query<T, execution::mapping_t::new_thread_t>::is_valid
1087   >::type>
1088 {
1089   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
1090     (is_same<typename static_query<T,
1091       execution::mapping_t::new_thread_t>::result_type,
1092         execution::mapping_t::new_thread_t>::value));
1093 };
1094 
1095 template <typename T>
1096 struct static_require<T, execution::mapping_t::other_t,
1097   typename enable_if<
1098     static_query<T, execution::mapping_t::other_t>::is_valid
1099   >::type>
1100 {
1101   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
1102     (is_same<typename static_query<T,
1103       execution::mapping_t::other_t>::result_type,
1104         execution::mapping_t::other_t>::value));
1105 };
1106 
1107 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)
1108 
1109 } // namespace traits
1110 
1111 #endif // defined(GENERATING_DOCUMENTATION)
1112 
1113 } // namespace asio
1114 } // namespace boost
1115 
1116 #include <boost/asio/detail/pop_options.hpp>
1117 
1118 #endif // BOOST_ASIO_EXECUTION_MAPPING_HPP
1119