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

source code of boost/libs/asio/include/boost/asio/execution/blocking.hpp