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