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