1 //
2 // execution/bulk_guarantee.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_BULK_GUARANTEE_HPP
12 #define BOOST_ASIO_EXECUTION_BULK_GUARANTEE_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 communicate the forward progress and ordering guarantees of
41 /// execution agents associated with the bulk execution.
42 struct bulk_guarantee_t
43 {
44   /// The bulk_guarantee_t property applies to executors, senders, and
45   /// schedulers.
46   template <typename T>
47   static constexpr bool is_applicable_property_v =
48     is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
49 
50   /// The top-level bulk_guarantee_t property cannot be required.
51   static constexpr bool is_requirable = false;
52 
53   /// The top-level bulk_guarantee_t property cannot be preferred.
54   static constexpr bool is_preferable = false;
55 
56   /// The type returned by queries against an @c any_executor.
57   typedef bulk_guarantee_t polymorphic_query_result_type;
58 
59   /// A sub-property that indicates that execution agents within the same bulk
60   /// execution may be parallelised and vectorised.
61   struct unsequenced_t
62   {
63     /// The bulk_guarantee_t::unsequenced_t property applies to executors,
64     /// senders, and schedulers.
65     template <typename T>
66     static constexpr bool is_applicable_property_v =
67       is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
68 
69     /// The bulk_guarantee_t::unsequenced_t property can be required.
70     static constexpr bool is_requirable = true;
71 
72     /// The bulk_guarantee_t::unsequenced_t property can be preferred.
73     static constexpr bool is_preferable = true;
74 
75     /// The type returned by queries against an @c any_executor.
76     typedef bulk_guarantee_t polymorphic_query_result_type;
77 
78     /// Default constructor.
79     constexpr unsequenced_t();
80 
81     /// Get the value associated with a property object.
82     /**
83      * @returns unsequenced_t();
84      */
85     static constexpr bulk_guarantee_t value();
86   };
87 
88   /// A sub-property that indicates that execution agents within the same bulk
89   /// execution may not be parallelised and vectorised.
90   struct sequenced_t
91   {
92     /// The bulk_guarantee_t::sequenced_t property applies to executors,
93     /// senders, and schedulers.
94     template <typename T>
95     static constexpr bool is_applicable_property_v =
96       is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
97 
98     /// The bulk_guarantee_t::sequenced_t property can be required.
99     static constexpr bool is_requirable = true;
100 
101     /// The bulk_guarantee_t::sequenced_t property can be preferred.
102     static constexpr bool is_preferable = true;
103 
104     /// The type returned by queries against an @c any_executor.
105     typedef bulk_guarantee_t polymorphic_query_result_type;
106 
107     /// Default constructor.
108     constexpr sequenced_t();
109 
110     /// Get the value associated with a property object.
111     /**
112      * @returns sequenced_t();
113      */
114     static constexpr bulk_guarantee_t value();
115   };
116 
117   /// A sub-property that indicates that execution agents within the same bulk
118   /// execution may be parallelised.
119   struct parallel_t
120   {
121     /// The bulk_guarantee_t::parallel_t property applies to executors,
122     /// senders, and schedulers.
123     template <typename T>
124     static constexpr bool is_applicable_property_v =
125       is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
126 
127     /// The bulk_guarantee_t::parallel_t property can be required.
128     static constexpr bool is_requirable = true;
129 
130     /// The bulk_guarantee_t::parallel_t property can be preferred.
131     static constexpr bool is_preferable = true;
132 
133     /// The type returned by queries against an @c any_executor.
134     typedef bulk_guarantee_t polymorphic_query_result_type;
135 
136     /// Default constructor.
137     constexpr parallel_t();
138 
139     /// Get the value associated with a property object.
140     /**
141      * @returns parallel_t();
142      */
143     static constexpr bulk_guarantee_t value();
144   };
145 
146   /// A special value used for accessing the bulk_guarantee_t::unsequenced_t
147   /// property.
148   static constexpr unsequenced_t unsequenced;
149 
150   /// A special value used for accessing the bulk_guarantee_t::sequenced_t
151   /// property.
152   static constexpr sequenced_t sequenced;
153 
154   /// A special value used for accessing the bulk_guarantee_t::parallel_t
155   /// property.
156   static constexpr parallel_t parallel;
157 
158   /// Default constructor.
159   constexpr bulk_guarantee_t();
160 
161   /// Construct from a sub-property value.
162   constexpr bulk_guarantee_t(unsequenced_t);
163 
164   /// Construct from a sub-property value.
165   constexpr bulk_guarantee_t(sequenced_t);
166 
167   /// Construct from a sub-property value.
168   constexpr bulk_guarantee_t(parallel_t);
169 
170   /// Compare property values for equality.
171   friend constexpr bool operator==(
172       const bulk_guarantee_t& a, const bulk_guarantee_t& b) noexcept;
173 
174   /// Compare property values for inequality.
175   friend constexpr bool operator!=(
176       const bulk_guarantee_t& a, const bulk_guarantee_t& b) noexcept;
177 };
178 
179 /// A special value used for accessing the bulk_guarantee_t property.
180 constexpr bulk_guarantee_t bulk_guarantee;
181 
182 } // namespace execution
183 
184 #else // defined(GENERATING_DOCUMENTATION)
185 
186 namespace execution {
187 namespace detail {
188 namespace bulk_guarantee {
189 
190 template <int I> struct unsequenced_t;
191 template <int I> struct sequenced_t;
192 template <int I> struct parallel_t;
193 
194 } // namespace bulk_guarantee
195 
196 template <int I = 0>
197 struct bulk_guarantee_t
198 {
199 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
200   template <typename T>
201   BOOST_ASIO_STATIC_CONSTEXPR(bool,
202     is_applicable_property_v = (
203       is_executor<T>::value
204         || conditional<
205             is_executor<T>::value,
206             false_type,
207             is_sender<T>
208           >::type::value
209         || conditional<
210             is_executor<T>::value,
211             false_type,
212             is_scheduler<T>
213           >::type::value));
214 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
215 
216   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);
217   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);
218   typedef bulk_guarantee_t polymorphic_query_result_type;
219 
220   typedef detail::bulk_guarantee::unsequenced_t<I> unsequenced_t;
221   typedef detail::bulk_guarantee::sequenced_t<I> sequenced_t;
222   typedef detail::bulk_guarantee::parallel_t<I> parallel_t;
223 
224   BOOST_ASIO_CONSTEXPR bulk_guarantee_t()
225     : value_(-1)
226   {
227   }
228 
229   BOOST_ASIO_CONSTEXPR bulk_guarantee_t(unsequenced_t)
230     : value_(0)
231   {
232   }
233 
234   BOOST_ASIO_CONSTEXPR bulk_guarantee_t(sequenced_t)
235     : value_(1)
236   {
237   }
238 
239   BOOST_ASIO_CONSTEXPR bulk_guarantee_t(parallel_t)
240     : value_(2)
241   {
242   }
243 
244   template <typename T>
245   struct proxy
246   {
247 #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
248     struct type
249     {
250       template <typename P>
251       auto query(BOOST_ASIO_MOVE_ARG(P) p) const
252         noexcept(
253           noexcept(
254             declval<typename conditional<true, T, P>::type>().query(
255               BOOST_ASIO_MOVE_CAST(P)(p))
256           )
257         )
258         -> decltype(
259           declval<typename conditional<true, T, P>::type>().query(
260             BOOST_ASIO_MOVE_CAST(P)(p))
261         );
262     };
263 #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
264     typedef T type;
265 #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
266   };
267 
268   template <typename T>
269   struct static_proxy
270   {
271 #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
272     struct type
273     {
274       template <typename P>
275       static constexpr auto query(BOOST_ASIO_MOVE_ARG(P) p)
276         noexcept(
277           noexcept(
278             conditional<true, T, P>::type::query(BOOST_ASIO_MOVE_CAST(P)(p))
279           )
280         )
281         -> decltype(
282           conditional<true, T, P>::type::query(BOOST_ASIO_MOVE_CAST(P)(p))
283         )
284       {
285         return T::query(BOOST_ASIO_MOVE_CAST(P)(p));
286       }
287     };
288 #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
289     typedef T type;
290 #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
291   };
292 
293   template <typename T>
294   struct query_member :
295     traits::query_member<typename proxy<T>::type, bulk_guarantee_t> {};
296 
297   template <typename T>
298   struct query_static_constexpr_member :
299     traits::query_static_constexpr_member<
300       typename static_proxy<T>::type, bulk_guarantee_t> {};
301 
302 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
303   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
304   template <typename T>
305   static BOOST_ASIO_CONSTEXPR
306   typename query_static_constexpr_member<T>::result_type
307   static_query()
308     BOOST_ASIO_NOEXCEPT_IF((
309       query_static_constexpr_member<T>::is_noexcept))
310   {
311     return query_static_constexpr_member<T>::value();
312   }
313 
314   template <typename T>
315   static BOOST_ASIO_CONSTEXPR
316   typename traits::static_query<T, unsequenced_t>::result_type
317   static_query(
318       typename enable_if<
319         !query_static_constexpr_member<T>::is_valid
320       >::type* = 0,
321       typename enable_if<
322         !query_member<T>::is_valid
323       >::type* = 0,
324       typename enable_if<
325         traits::static_query<T, unsequenced_t>::is_valid
326       >::type* = 0) BOOST_ASIO_NOEXCEPT
327   {
328     return traits::static_query<T, unsequenced_t>::value();
329   }
330 
331   template <typename T>
332   static BOOST_ASIO_CONSTEXPR
333   typename traits::static_query<T, sequenced_t>::result_type
334   static_query(
335       typename enable_if<
336         !query_static_constexpr_member<T>::is_valid
337       >::type* = 0,
338       typename enable_if<
339         !query_member<T>::is_valid
340       >::type* = 0,
341       typename enable_if<
342         !traits::static_query<T, unsequenced_t>::is_valid
343       >::type* = 0,
344       typename enable_if<
345         traits::static_query<T, sequenced_t>::is_valid
346       >::type* = 0) BOOST_ASIO_NOEXCEPT
347   {
348     return traits::static_query<T, sequenced_t>::value();
349   }
350 
351   template <typename T>
352   static BOOST_ASIO_CONSTEXPR
353   typename traits::static_query<T, parallel_t>::result_type
354   static_query(
355       typename enable_if<
356         !query_static_constexpr_member<T>::is_valid
357       >::type* = 0,
358       typename enable_if<
359         !query_member<T>::is_valid
360       >::type* = 0,
361       typename enable_if<
362         !traits::static_query<T, unsequenced_t>::is_valid
363       >::type* = 0,
364       typename enable_if<
365         !traits::static_query<T, sequenced_t>::is_valid
366       >::type* = 0,
367       typename enable_if<
368         traits::static_query<T, parallel_t>::is_valid
369       >::type* = 0) BOOST_ASIO_NOEXCEPT
370   {
371     return traits::static_query<T, parallel_t>::value();
372   }
373 
374   template <typename E,
375       typename T = decltype(bulk_guarantee_t::static_query<E>())>
376   static BOOST_ASIO_CONSTEXPR const T static_query_v
377     = bulk_guarantee_t::static_query<E>();
378 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
379        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
380 
381   friend BOOST_ASIO_CONSTEXPR bool operator==(
382       const bulk_guarantee_t& a, const bulk_guarantee_t& b)
383   {
384     return a.value_ == b.value_;
385   }
386 
387   friend BOOST_ASIO_CONSTEXPR bool operator!=(
388       const bulk_guarantee_t& a, const bulk_guarantee_t& b)
389   {
390     return a.value_ != b.value_;
391   }
392 
393   struct convertible_from_bulk_guarantee_t
394   {
395     BOOST_ASIO_CONSTEXPR convertible_from_bulk_guarantee_t(bulk_guarantee_t) {}
396   };
397 
398   template <typename Executor>
399   friend BOOST_ASIO_CONSTEXPR bulk_guarantee_t query(
400       const Executor& ex, convertible_from_bulk_guarantee_t,
401       typename enable_if<
402         can_query<const Executor&, unsequenced_t>::value
403       >::type* = 0)
404 #if !defined(__clang__) // Clang crashes if noexcept is used here.
405 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
406     BOOST_ASIO_NOEXCEPT_IF((
407       is_nothrow_query<const Executor&,
408         bulk_guarantee_t<>::unsequenced_t>::value))
409 #else // defined(BOOST_ASIO_MSVC)
410     BOOST_ASIO_NOEXCEPT_IF((
411       is_nothrow_query<const Executor&, unsequenced_t>::value))
412 #endif // defined(BOOST_ASIO_MSVC)
413 #endif // !defined(__clang__)
414   {
415     return boost::asio::query(ex, unsequenced_t());
416   }
417 
418   template <typename Executor>
419   friend BOOST_ASIO_CONSTEXPR bulk_guarantee_t query(
420       const Executor& ex, convertible_from_bulk_guarantee_t,
421       typename enable_if<
422         !can_query<const Executor&, unsequenced_t>::value
423       >::type* = 0,
424       typename enable_if<
425         can_query<const Executor&, sequenced_t>::value
426       >::type* = 0)
427 #if !defined(__clang__) // Clang crashes if noexcept is used here.
428 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
429     BOOST_ASIO_NOEXCEPT_IF((
430       is_nothrow_query<const Executor&,
431         bulk_guarantee_t<>::sequenced_t>::value))
432 #else // defined(BOOST_ASIO_MSVC)
433     BOOST_ASIO_NOEXCEPT_IF((
434       is_nothrow_query<const Executor&, sequenced_t>::value))
435 #endif // defined(BOOST_ASIO_MSVC)
436 #endif // !defined(__clang__)
437   {
438     return boost::asio::query(ex, sequenced_t());
439   }
440 
441   template <typename Executor>
442   friend BOOST_ASIO_CONSTEXPR bulk_guarantee_t query(
443       const Executor& ex, convertible_from_bulk_guarantee_t,
444       typename enable_if<
445         !can_query<const Executor&, unsequenced_t>::value
446       >::type* = 0,
447       typename enable_if<
448         !can_query<const Executor&, sequenced_t>::value
449       >::type* = 0,
450       typename enable_if<
451         can_query<const Executor&, parallel_t>::value
452       >::type* = 0)
453 #if !defined(__clang__) // Clang crashes if noexcept is used here.
454 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
455     BOOST_ASIO_NOEXCEPT_IF((
456       is_nothrow_query<const Executor&, bulk_guarantee_t<>::parallel_t>::value))
457 #else // defined(BOOST_ASIO_MSVC)
458     BOOST_ASIO_NOEXCEPT_IF((
459       is_nothrow_query<const Executor&, parallel_t>::value))
460 #endif // defined(BOOST_ASIO_MSVC)
461 #endif // !defined(__clang__)
462   {
463     return boost::asio::query(ex, parallel_t());
464   }
465 
466   BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(unsequenced_t, unsequenced);
467   BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(sequenced_t, sequenced);
468   BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(parallel_t, parallel);
469 
470 #if !defined(BOOST_ASIO_HAS_CONSTEXPR)
471   static const bulk_guarantee_t instance;
472 #endif // !defined(BOOST_ASIO_HAS_CONSTEXPR)
473 
474 private:
475   int value_;
476 };
477 
478 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
479   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
480 template <int I> template <typename E, typename T>
481 const T bulk_guarantee_t<I>::static_query_v;
482 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
483        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
484 
485 #if !defined(BOOST_ASIO_HAS_CONSTEXPR)
486 template <int I>
487 const bulk_guarantee_t<I> bulk_guarantee_t<I>::instance;
488 #endif
489 
490 template <int I>
491 const typename bulk_guarantee_t<I>::unsequenced_t
492 bulk_guarantee_t<I>::unsequenced;
493 
494 template <int I>
495 const typename bulk_guarantee_t<I>::sequenced_t
496 bulk_guarantee_t<I>::sequenced;
497 
498 template <int I>
499 const typename bulk_guarantee_t<I>::parallel_t
500 bulk_guarantee_t<I>::parallel;
501 
502 namespace bulk_guarantee {
503 
504 template <int I = 0>
505 struct unsequenced_t
506 {
507 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
508   template <typename T>
509   BOOST_ASIO_STATIC_CONSTEXPR(bool,
510     is_applicable_property_v = (
511       is_executor<T>::value
512         || conditional<
513             is_executor<T>::value,
514             false_type,
515             is_sender<T>
516           >::type::value
517         || conditional<
518             is_executor<T>::value,
519             false_type,
520             is_scheduler<T>
521           >::type::value));
522 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
523 
524   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
525   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
526   typedef bulk_guarantee_t<I> polymorphic_query_result_type;
527 
528   BOOST_ASIO_CONSTEXPR unsequenced_t()
529   {
530   }
531 
532   template <typename T>
533   struct query_member :
534     traits::query_member<
535       typename bulk_guarantee_t<I>::template proxy<T>::type,
536         unsequenced_t> {};
537 
538   template <typename T>
539   struct query_static_constexpr_member :
540     traits::query_static_constexpr_member<
541       typename bulk_guarantee_t<I>::template static_proxy<T>::type,
542         unsequenced_t> {};
543 
544 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
545   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
546   template <typename T>
547   static BOOST_ASIO_CONSTEXPR
548   typename query_static_constexpr_member<T>::result_type
549   static_query()
550     BOOST_ASIO_NOEXCEPT_IF((
551       query_static_constexpr_member<T>::is_noexcept))
552   {
553     return query_static_constexpr_member<T>::value();
554   }
555 
556   template <typename T>
557   static BOOST_ASIO_CONSTEXPR unsequenced_t static_query(
558       typename enable_if<
559         !query_static_constexpr_member<T>::is_valid
560       >::type* = 0,
561       typename enable_if<
562         !query_member<T>::is_valid
563       >::type* = 0,
564       typename enable_if<
565         !traits::query_free<T, unsequenced_t>::is_valid
566       >::type* = 0,
567       typename enable_if<
568         !can_query<T, sequenced_t<I> >::value
569       >::type* = 0,
570       typename enable_if<
571         !can_query<T, parallel_t<I> >::value
572       >::type* = 0) BOOST_ASIO_NOEXCEPT
573   {
574     return unsequenced_t();
575   }
576 
577   template <typename E, typename T = decltype(unsequenced_t::static_query<E>())>
578   static BOOST_ASIO_CONSTEXPR const T static_query_v
579     = unsequenced_t::static_query<E>();
580 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
581        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
582 
583   static BOOST_ASIO_CONSTEXPR bulk_guarantee_t<I> value()
584   {
585     return unsequenced_t();
586   }
587 
588   friend BOOST_ASIO_CONSTEXPR bool operator==(
589       const unsequenced_t&, const unsequenced_t&)
590   {
591     return true;
592   }
593 
594   friend BOOST_ASIO_CONSTEXPR bool operator!=(
595       const unsequenced_t&, const unsequenced_t&)
596   {
597     return false;
598   }
599 
600   friend BOOST_ASIO_CONSTEXPR bool operator==(
601       const unsequenced_t&, const sequenced_t<I>&)
602   {
603     return false;
604   }
605 
606   friend BOOST_ASIO_CONSTEXPR bool operator!=(
607       const unsequenced_t&, const sequenced_t<I>&)
608   {
609     return true;
610   }
611 
612   friend BOOST_ASIO_CONSTEXPR bool operator==(
613       const unsequenced_t&, const parallel_t<I>&)
614   {
615     return false;
616   }
617 
618   friend BOOST_ASIO_CONSTEXPR bool operator!=(
619       const unsequenced_t&, const parallel_t<I>&)
620   {
621     return true;
622   }
623 };
624 
625 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
626   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
627 template <int I> template <typename E, typename T>
628 const T unsequenced_t<I>::static_query_v;
629 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
630        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
631 
632 template <int I = 0>
633 struct sequenced_t
634 {
635 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
636   template <typename T>
637   BOOST_ASIO_STATIC_CONSTEXPR(bool,
638     is_applicable_property_v = (
639       is_executor<T>::value
640         || conditional<
641             is_executor<T>::value,
642             false_type,
643             is_sender<T>
644           >::type::value
645         || conditional<
646             is_executor<T>::value,
647             false_type,
648             is_scheduler<T>
649           >::type::value));
650 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
651 
652   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
653   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
654   typedef bulk_guarantee_t<I> polymorphic_query_result_type;
655 
656   BOOST_ASIO_CONSTEXPR sequenced_t()
657   {
658   }
659 
660   template <typename T>
661   struct query_member :
662     traits::query_member<
663       typename bulk_guarantee_t<I>::template proxy<T>::type,
664         sequenced_t> {};
665 
666   template <typename T>
667   struct query_static_constexpr_member :
668     traits::query_static_constexpr_member<
669       typename bulk_guarantee_t<I>::template static_proxy<T>::type,
670         sequenced_t> {};
671 
672 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
673   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
674   template <typename T>
675   static BOOST_ASIO_CONSTEXPR
676   typename query_static_constexpr_member<T>::result_type
677   static_query()
678     BOOST_ASIO_NOEXCEPT_IF((
679       query_static_constexpr_member<T>::is_noexcept))
680   {
681     return query_static_constexpr_member<T>::value();
682   }
683 
684   template <typename E, typename T = decltype(sequenced_t::static_query<E>())>
685   static BOOST_ASIO_CONSTEXPR const T static_query_v
686     = sequenced_t::static_query<E>();
687 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
688        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
689 
690   static BOOST_ASIO_CONSTEXPR bulk_guarantee_t<I> value()
691   {
692     return sequenced_t();
693   }
694 
695   friend BOOST_ASIO_CONSTEXPR bool operator==(
696       const sequenced_t&, const sequenced_t&)
697   {
698     return true;
699   }
700 
701   friend BOOST_ASIO_CONSTEXPR bool operator!=(
702       const sequenced_t&, const sequenced_t&)
703   {
704     return false;
705   }
706 
707   friend BOOST_ASIO_CONSTEXPR bool operator==(
708       const sequenced_t&, const unsequenced_t<I>&)
709   {
710     return false;
711   }
712 
713   friend BOOST_ASIO_CONSTEXPR bool operator!=(
714       const sequenced_t&, const unsequenced_t<I>&)
715   {
716     return true;
717   }
718 
719   friend BOOST_ASIO_CONSTEXPR bool operator==(
720       const sequenced_t&, const parallel_t<I>&)
721   {
722     return false;
723   }
724 
725   friend BOOST_ASIO_CONSTEXPR bool operator!=(
726       const sequenced_t&, const parallel_t<I>&)
727   {
728     return true;
729   }
730 };
731 
732 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
733   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
734 template <int I> template <typename E, typename T>
735 const T sequenced_t<I>::static_query_v;
736 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
737        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
738 
739 template <int I>
740 struct parallel_t
741 {
742 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
743   template <typename T>
744   BOOST_ASIO_STATIC_CONSTEXPR(bool,
745     is_applicable_property_v = (
746       is_executor<T>::value
747         || conditional<
748             is_executor<T>::value,
749             false_type,
750             is_sender<T>
751           >::type::value
752         || conditional<
753             is_executor<T>::value,
754             false_type,
755             is_scheduler<T>
756           >::type::value));
757 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
758 
759   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
760   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
761   typedef bulk_guarantee_t<I> polymorphic_query_result_type;
762 
763   BOOST_ASIO_CONSTEXPR parallel_t()
764   {
765   }
766 
767   template <typename T>
768   struct query_member :
769     traits::query_member<
770       typename bulk_guarantee_t<I>::template proxy<T>::type,
771         parallel_t> {};
772 
773   template <typename T>
774   struct query_static_constexpr_member :
775     traits::query_static_constexpr_member<
776       typename bulk_guarantee_t<I>::template static_proxy<T>::type,
777         parallel_t> {};
778 
779 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
780   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
781   template <typename T>
782   static BOOST_ASIO_CONSTEXPR
783   typename query_static_constexpr_member<T>::result_type
784   static_query()
785     BOOST_ASIO_NOEXCEPT_IF((
786       query_static_constexpr_member<T>::is_noexcept))
787   {
788     return query_static_constexpr_member<T>::value();
789   }
790 
791   template <typename E, typename T = decltype(parallel_t::static_query<E>())>
792   static BOOST_ASIO_CONSTEXPR const T static_query_v
793     = parallel_t::static_query<E>();
794 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
795        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
796 
797   static BOOST_ASIO_CONSTEXPR bulk_guarantee_t<I> value()
798   {
799     return parallel_t();
800   }
801 
802   friend BOOST_ASIO_CONSTEXPR bool operator==(
803       const parallel_t&, const parallel_t&)
804   {
805     return true;
806   }
807 
808   friend BOOST_ASIO_CONSTEXPR bool operator!=(
809       const parallel_t&, const parallel_t&)
810   {
811     return false;
812   }
813 
814   friend BOOST_ASIO_CONSTEXPR bool operator==(
815       const parallel_t&, const unsequenced_t<I>&)
816   {
817     return false;
818   }
819 
820   friend BOOST_ASIO_CONSTEXPR bool operator!=(
821       const parallel_t&, const unsequenced_t<I>&)
822   {
823     return true;
824   }
825 
826   friend BOOST_ASIO_CONSTEXPR bool operator==(
827       const parallel_t&, const sequenced_t<I>&)
828   {
829     return false;
830   }
831 
832   friend BOOST_ASIO_CONSTEXPR bool operator!=(
833       const parallel_t&, const sequenced_t<I>&)
834   {
835     return true;
836   }
837 };
838 
839 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
840   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
841 template <int I> template <typename E, typename T>
842 const T parallel_t<I>::static_query_v;
843 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
844        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
845 
846 } // namespace bulk_guarantee
847 } // namespace detail
848 
849 typedef detail::bulk_guarantee_t<> bulk_guarantee_t;
850 
851 #if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
852 constexpr bulk_guarantee_t bulk_guarantee;
853 #else // defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
854 namespace { static const bulk_guarantee_t&
855   bulk_guarantee = bulk_guarantee_t::instance; }
856 #endif
857 
858 } // namespace execution
859 
860 #if !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
861 
862 template <typename T>
863 struct is_applicable_property<T, execution::bulk_guarantee_t>
864   : integral_constant<bool,
865       execution::is_executor<T>::value
866         || conditional<
867             execution::is_executor<T>::value,
868             false_type,
869             execution::is_sender<T>
870           >::type::value
871         || conditional<
872             execution::is_executor<T>::value,
873             false_type,
874             execution::is_scheduler<T>
875           >::type::value>
876 {
877 };
878 
879 template <typename T>
880 struct is_applicable_property<T, execution::bulk_guarantee_t::unsequenced_t>
881   : integral_constant<bool,
882       execution::is_executor<T>::value
883         || conditional<
884             execution::is_executor<T>::value,
885             false_type,
886             execution::is_sender<T>
887           >::type::value
888         || conditional<
889             execution::is_executor<T>::value,
890             false_type,
891             execution::is_scheduler<T>
892           >::type::value>
893 {
894 };
895 
896 template <typename T>
897 struct is_applicable_property<T, execution::bulk_guarantee_t::sequenced_t>
898   : integral_constant<bool,
899       execution::is_executor<T>::value
900         || conditional<
901             execution::is_executor<T>::value,
902             false_type,
903             execution::is_sender<T>
904           >::type::value
905         || conditional<
906             execution::is_executor<T>::value,
907             false_type,
908             execution::is_scheduler<T>
909           >::type::value>
910 {
911 };
912 
913 template <typename T>
914 struct is_applicable_property<T, execution::bulk_guarantee_t::parallel_t>
915   : integral_constant<bool,
916       execution::is_executor<T>::value
917         || conditional<
918             execution::is_executor<T>::value,
919             false_type,
920             execution::is_sender<T>
921           >::type::value
922         || conditional<
923             execution::is_executor<T>::value,
924             false_type,
925             execution::is_scheduler<T>
926           >::type::value>
927 {
928 };
929 
930 #endif // !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
931 
932 namespace traits {
933 
934 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
935 
936 template <typename T>
937 struct query_free_default<T, execution::bulk_guarantee_t,
938   typename enable_if<
939     can_query<T, execution::bulk_guarantee_t::unsequenced_t>::value
940   >::type>
941 {
942   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
943   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
944     (is_nothrow_query<T, execution::bulk_guarantee_t::unsequenced_t>::value));
945 
946   typedef execution::bulk_guarantee_t result_type;
947 };
948 
949 template <typename T>
950 struct query_free_default<T, execution::bulk_guarantee_t,
951   typename enable_if<
952     !can_query<T, execution::bulk_guarantee_t::unsequenced_t>::value
953       && can_query<T, execution::bulk_guarantee_t::sequenced_t>::value
954   >::type>
955 {
956   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
957   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
958     (is_nothrow_query<T, execution::bulk_guarantee_t::sequenced_t>::value));
959 
960   typedef execution::bulk_guarantee_t result_type;
961 };
962 
963 template <typename T>
964 struct query_free_default<T, execution::bulk_guarantee_t,
965   typename enable_if<
966     !can_query<T, execution::bulk_guarantee_t::unsequenced_t>::value
967       && !can_query<T, execution::bulk_guarantee_t::sequenced_t>::value
968       && can_query<T, execution::bulk_guarantee_t::parallel_t>::value
969   >::type>
970 {
971   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
972   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
973     (is_nothrow_query<T, execution::bulk_guarantee_t::parallel_t>::value));
974 
975   typedef execution::bulk_guarantee_t result_type;
976 };
977 
978 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
979 
980 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
981   || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
982 
983 template <typename T>
984 struct static_query<T, execution::bulk_guarantee_t,
985   typename enable_if<
986     execution::detail::bulk_guarantee_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::bulk_guarantee_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::bulk_guarantee_t<0>::
999       query_static_constexpr_member<T>::value();
1000   }
1001 };
1002 
1003 template <typename T>
1004 struct static_query<T, execution::bulk_guarantee_t,
1005   typename enable_if<
1006     !execution::detail::bulk_guarantee_t<0>::
1007         query_static_constexpr_member<T>::is_valid
1008       && !execution::detail::bulk_guarantee_t<0>::
1009         query_member<T>::is_valid
1010       && traits::static_query<T,
1011         execution::bulk_guarantee_t::unsequenced_t>::is_valid
1012   >::type>
1013 {
1014   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
1015   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
1016 
1017   typedef typename traits::static_query<T,
1018     execution::bulk_guarantee_t::unsequenced_t>::result_type result_type;
1019 
1020   static BOOST_ASIO_CONSTEXPR result_type value()
1021   {
1022     return traits::static_query<T,
1023         execution::bulk_guarantee_t::unsequenced_t>::value();
1024   }
1025 };
1026 
1027 template <typename T>
1028 struct static_query<T, execution::bulk_guarantee_t,
1029   typename enable_if<
1030     !execution::detail::bulk_guarantee_t<0>::
1031         query_static_constexpr_member<T>::is_valid
1032       && !execution::detail::bulk_guarantee_t<0>::
1033         query_member<T>::is_valid
1034       && !traits::static_query<T,
1035         execution::bulk_guarantee_t::unsequenced_t>::is_valid
1036       && traits::static_query<T,
1037         execution::bulk_guarantee_t::sequenced_t>::is_valid
1038   >::type>
1039 {
1040   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
1041   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
1042 
1043   typedef typename traits::static_query<T,
1044     execution::bulk_guarantee_t::sequenced_t>::result_type result_type;
1045 
1046   static BOOST_ASIO_CONSTEXPR result_type value()
1047   {
1048     return traits::static_query<T,
1049         execution::bulk_guarantee_t::sequenced_t>::value();
1050   }
1051 };
1052 
1053 template <typename T>
1054 struct static_query<T, execution::bulk_guarantee_t,
1055   typename enable_if<
1056     !execution::detail::bulk_guarantee_t<0>::
1057         query_static_constexpr_member<T>::is_valid
1058       && !execution::detail::bulk_guarantee_t<0>::
1059         query_member<T>::is_valid
1060       && !traits::static_query<T,
1061         execution::bulk_guarantee_t::unsequenced_t>::is_valid
1062       && !traits::static_query<T,
1063         execution::bulk_guarantee_t::sequenced_t>::is_valid
1064       && traits::static_query<T,
1065         execution::bulk_guarantee_t::parallel_t>::is_valid
1066   >::type>
1067 {
1068   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
1069   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
1070 
1071   typedef typename traits::static_query<T,
1072     execution::bulk_guarantee_t::parallel_t>::result_type result_type;
1073 
1074   static BOOST_ASIO_CONSTEXPR result_type value()
1075   {
1076     return traits::static_query<T,
1077         execution::bulk_guarantee_t::parallel_t>::value();
1078   }
1079 };
1080 
1081 template <typename T>
1082 struct static_query<T, execution::bulk_guarantee_t::unsequenced_t,
1083   typename enable_if<
1084     execution::detail::bulk_guarantee::unsequenced_t<0>::
1085       query_static_constexpr_member<T>::is_valid
1086   >::type>
1087 {
1088   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
1089   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
1090 
1091   typedef typename execution::detail::bulk_guarantee::unsequenced_t<0>::
1092     query_static_constexpr_member<T>::result_type result_type;
1093 
1094   static BOOST_ASIO_CONSTEXPR result_type value()
1095   {
1096     return execution::detail::bulk_guarantee::unsequenced_t<0>::
1097       query_static_constexpr_member<T>::value();
1098   }
1099 };
1100 
1101 template <typename T>
1102 struct static_query<T, execution::bulk_guarantee_t::unsequenced_t,
1103   typename enable_if<
1104     !execution::detail::bulk_guarantee::unsequenced_t<0>::
1105         query_static_constexpr_member<T>::is_valid
1106       && !execution::detail::bulk_guarantee::unsequenced_t<0>::
1107         query_member<T>::is_valid
1108       && !traits::query_free<T,
1109         execution::bulk_guarantee_t::unsequenced_t>::is_valid
1110       && !can_query<T, execution::bulk_guarantee_t::sequenced_t>::value
1111       && !can_query<T, execution::bulk_guarantee_t::parallel_t>::value
1112   >::type>
1113 {
1114   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
1115   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
1116 
1117   typedef execution::bulk_guarantee_t::unsequenced_t result_type;
1118 
1119   static BOOST_ASIO_CONSTEXPR result_type value()
1120   {
1121     return result_type();
1122   }
1123 };
1124 
1125 template <typename T>
1126 struct static_query<T, execution::bulk_guarantee_t::sequenced_t,
1127   typename enable_if<
1128     execution::detail::bulk_guarantee::sequenced_t<0>::
1129       query_static_constexpr_member<T>::is_valid
1130   >::type>
1131 {
1132   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
1133   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
1134 
1135   typedef typename execution::detail::bulk_guarantee::sequenced_t<0>::
1136     query_static_constexpr_member<T>::result_type result_type;
1137 
1138   static BOOST_ASIO_CONSTEXPR result_type value()
1139   {
1140     return execution::detail::bulk_guarantee::sequenced_t<0>::
1141       query_static_constexpr_member<T>::value();
1142   }
1143 };
1144 
1145 template <typename T>
1146 struct static_query<T, execution::bulk_guarantee_t::parallel_t,
1147   typename enable_if<
1148     execution::detail::bulk_guarantee::parallel_t<0>::
1149       query_static_constexpr_member<T>::is_valid
1150   >::type>
1151 {
1152   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
1153   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
1154 
1155   typedef typename execution::detail::bulk_guarantee::parallel_t<0>::
1156     query_static_constexpr_member<T>::result_type result_type;
1157 
1158   static BOOST_ASIO_CONSTEXPR result_type value()
1159   {
1160     return execution::detail::bulk_guarantee::parallel_t<0>::
1161       query_static_constexpr_member<T>::value();
1162   }
1163 };
1164 
1165 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
1166        //   || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
1167 
1168 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)
1169 
1170 template <typename T>
1171 struct static_require<T, execution::bulk_guarantee_t::unsequenced_t,
1172   typename enable_if<
1173     static_query<T, execution::bulk_guarantee_t::unsequenced_t>::is_valid
1174   >::type>
1175 {
1176   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
1177     (is_same<typename static_query<T,
1178       execution::bulk_guarantee_t::unsequenced_t>::result_type,
1179         execution::bulk_guarantee_t::unsequenced_t>::value));
1180 };
1181 
1182 template <typename T>
1183 struct static_require<T, execution::bulk_guarantee_t::sequenced_t,
1184   typename enable_if<
1185     static_query<T, execution::bulk_guarantee_t::sequenced_t>::is_valid
1186   >::type>
1187 {
1188   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
1189     (is_same<typename static_query<T,
1190       execution::bulk_guarantee_t::sequenced_t>::result_type,
1191         execution::bulk_guarantee_t::sequenced_t>::value));
1192 };
1193 
1194 template <typename T>
1195 struct static_require<T, execution::bulk_guarantee_t::parallel_t,
1196   typename enable_if<
1197     static_query<T, execution::bulk_guarantee_t::parallel_t>::is_valid
1198   >::type>
1199 {
1200   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
1201     (is_same<typename static_query<T,
1202       execution::bulk_guarantee_t::parallel_t>::result_type,
1203         execution::bulk_guarantee_t::parallel_t>::value));
1204 };
1205 
1206 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)
1207 
1208 } // namespace traits
1209 
1210 #endif // defined(GENERATING_DOCUMENTATION)
1211 
1212 } // namespace asio
1213 } // namespace boost
1214 
1215 #include <boost/asio/detail/pop_options.hpp>
1216 
1217 #endif // BOOST_ASIO_EXECUTION_BULK_GUARANTEE_HPP
1218