Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:43:17

0001 //
0002 // execution/blocking_adaptation.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2025 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_EXECUTION_BLOCKING_ADAPTATION_HPP
0012 #define BOOST_ASIO_EXECUTION_BLOCKING_ADAPTATION_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 #include <boost/asio/detail/event.hpp>
0020 #include <boost/asio/detail/mutex.hpp>
0021 #include <boost/asio/detail/type_traits.hpp>
0022 #include <boost/asio/execution/executor.hpp>
0023 #include <boost/asio/is_applicable_property.hpp>
0024 #include <boost/asio/prefer.hpp>
0025 #include <boost/asio/query.hpp>
0026 #include <boost/asio/require.hpp>
0027 #include <boost/asio/traits/prefer_member.hpp>
0028 #include <boost/asio/traits/query_free.hpp>
0029 #include <boost/asio/traits/query_member.hpp>
0030 #include <boost/asio/traits/query_static_constexpr_member.hpp>
0031 #include <boost/asio/traits/require_member.hpp>
0032 #include <boost/asio/traits/static_query.hpp>
0033 #include <boost/asio/traits/static_require.hpp>
0034 
0035 #include <boost/asio/detail/push_options.hpp>
0036 
0037 namespace boost {
0038 namespace asio {
0039 
0040 #if defined(GENERATING_DOCUMENTATION)
0041 
0042 namespace execution {
0043 
0044 /// A property to describe whether automatic adaptation of an executor is
0045 /// allowed in order to apply the blocking_adaptation_t::allowed_t property.
0046 struct blocking_adaptation_t
0047 {
0048   /// The blocking_adaptation_t property applies to executors.
0049   template <typename T>
0050   static constexpr bool is_applicable_property_v = is_executor_v<T>;
0051 
0052   /// The top-level blocking_adaptation_t property cannot be required.
0053   static constexpr bool is_requirable = false;
0054 
0055   /// The top-level blocking_adaptation_t property cannot be preferred.
0056   static constexpr bool is_preferable = false;
0057 
0058   /// The type returned by queries against an @c any_executor.
0059   typedef blocking_adaptation_t polymorphic_query_result_type;
0060 
0061   /// A sub-property that indicates that automatic adaptation is not allowed.
0062   struct disallowed_t
0063   {
0064     /// The blocking_adaptation_t::disallowed_t property applies to executors.
0065     template <typename T>
0066     static constexpr bool is_applicable_property_v = is_executor_v<T>;
0067 
0068     /// The blocking_adaptation_t::disallowed_t property can be required.
0069     static constexpr bool is_requirable = true;
0070 
0071     /// The blocking_adaptation_t::disallowed_t property can be preferred.
0072     static constexpr bool is_preferable = true;
0073 
0074     /// The type returned by queries against an @c any_executor.
0075     typedef blocking_adaptation_t polymorphic_query_result_type;
0076 
0077     /// Default constructor.
0078     constexpr disallowed_t();
0079 
0080     /// Get the value associated with a property object.
0081     /**
0082      * @returns disallowed_t();
0083      */
0084     static constexpr blocking_adaptation_t value();
0085   };
0086 
0087   /// A sub-property that indicates that automatic adaptation is allowed.
0088   struct allowed_t
0089   {
0090     /// The blocking_adaptation_t::allowed_t property applies to executors.
0091     template <typename T>
0092     static constexpr bool is_applicable_property_v = is_executor_v<T>;
0093 
0094     /// The blocking_adaptation_t::allowed_t property can be required.
0095     static constexpr bool is_requirable = true;
0096 
0097     /// The blocking_adaptation_t::allowed_t property can be preferred.
0098     static constexpr bool is_preferable = false;
0099 
0100     /// The type returned by queries against an @c any_executor.
0101     typedef blocking_adaptation_t polymorphic_query_result_type;
0102 
0103     /// Default constructor.
0104     constexpr allowed_t();
0105 
0106     /// Get the value associated with a property object.
0107     /**
0108      * @returns allowed_t();
0109      */
0110     static constexpr blocking_adaptation_t value();
0111   };
0112 
0113   /// A special value used for accessing the blocking_adaptation_t::disallowed_t
0114   /// property.
0115   static constexpr disallowed_t disallowed;
0116 
0117   /// A special value used for accessing the blocking_adaptation_t::allowed_t
0118   /// property.
0119   static constexpr allowed_t allowed;
0120 
0121   /// Default constructor.
0122   constexpr blocking_adaptation_t();
0123 
0124   /// Construct from a sub-property value.
0125   constexpr blocking_adaptation_t(disallowed_t);
0126 
0127   /// Construct from a sub-property value.
0128   constexpr blocking_adaptation_t(allowed_t);
0129 
0130   /// Compare property values for equality.
0131   friend constexpr bool operator==(
0132       const blocking_adaptation_t& a, const blocking_adaptation_t& b) noexcept;
0133 
0134   /// Compare property values for inequality.
0135   friend constexpr bool operator!=(
0136       const blocking_adaptation_t& a, const blocking_adaptation_t& b) noexcept;
0137 };
0138 
0139 /// A special value used for accessing the blocking_adaptation_t property.
0140 constexpr blocking_adaptation_t blocking_adaptation;
0141 
0142 } // namespace execution
0143 
0144 #else // defined(GENERATING_DOCUMENTATION)
0145 
0146 namespace execution {
0147 namespace detail {
0148 namespace blocking_adaptation {
0149 
0150 template <int I> struct disallowed_t;
0151 template <int I> struct allowed_t;
0152 
0153 } // namespace blocking_adaptation
0154 
0155 template <int I = 0>
0156 struct blocking_adaptation_t
0157 {
0158 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
0159   template <typename T>
0160   static constexpr bool is_applicable_property_v = is_executor<T>::value;
0161 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
0162 
0163   static constexpr bool is_requirable = false;
0164   static constexpr bool is_preferable = false;
0165   typedef blocking_adaptation_t polymorphic_query_result_type;
0166 
0167   typedef detail::blocking_adaptation::disallowed_t<I> disallowed_t;
0168   typedef detail::blocking_adaptation::allowed_t<I> allowed_t;
0169 
0170   constexpr blocking_adaptation_t()
0171     : value_(-1)
0172   {
0173   }
0174 
0175   constexpr blocking_adaptation_t(disallowed_t)
0176     : value_(0)
0177   {
0178   }
0179 
0180   constexpr blocking_adaptation_t(allowed_t)
0181     : value_(1)
0182   {
0183   }
0184 
0185   template <typename T>
0186   struct proxy
0187   {
0188 #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
0189     struct type
0190     {
0191       template <typename P>
0192       auto query(P&& p) const
0193         noexcept(
0194           noexcept(
0195             declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p))
0196           )
0197         )
0198         -> decltype(
0199           declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p))
0200         );
0201     };
0202 #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
0203     typedef T type;
0204 #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
0205   };
0206 
0207   template <typename T>
0208   struct static_proxy
0209   {
0210 #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
0211     struct type
0212     {
0213       template <typename P>
0214       static constexpr auto query(P&& p)
0215         noexcept(
0216           noexcept(
0217             conditional_t<true, T, P>::query(static_cast<P&&>(p))
0218           )
0219         )
0220         -> decltype(
0221           conditional_t<true, T, P>::query(static_cast<P&&>(p))
0222         )
0223       {
0224         return T::query(static_cast<P&&>(p));
0225       }
0226     };
0227 #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
0228     typedef T type;
0229 #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
0230   };
0231 
0232   template <typename T>
0233   struct query_member :
0234     traits::query_member<typename proxy<T>::type, blocking_adaptation_t> {};
0235 
0236   template <typename T>
0237   struct query_static_constexpr_member :
0238     traits::query_static_constexpr_member<
0239       typename static_proxy<T>::type, blocking_adaptation_t> {};
0240 
0241 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
0242   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
0243   template <typename T>
0244   static constexpr typename query_static_constexpr_member<T>::result_type
0245   static_query()
0246     noexcept(query_static_constexpr_member<T>::is_noexcept)
0247   {
0248     return query_static_constexpr_member<T>::value();
0249   }
0250 
0251   template <typename T>
0252   static constexpr
0253   typename traits::static_query<T, disallowed_t>::result_type
0254   static_query(
0255       enable_if_t<
0256         !query_static_constexpr_member<T>::is_valid
0257       >* = 0,
0258       enable_if_t<
0259         !query_member<T>::is_valid
0260       >* = 0,
0261       enable_if_t<
0262         traits::static_query<T, disallowed_t>::is_valid
0263       >* = 0) noexcept
0264   {
0265     return traits::static_query<T, disallowed_t>::value();
0266   }
0267 
0268   template <typename T>
0269   static constexpr
0270   typename traits::static_query<T, allowed_t>::result_type
0271   static_query(
0272       enable_if_t<
0273         !query_static_constexpr_member<T>::is_valid
0274       >* = 0,
0275       enable_if_t<
0276         !query_member<T>::is_valid
0277       >* = 0,
0278       enable_if_t<
0279         !traits::static_query<T, disallowed_t>::is_valid
0280       >* = 0,
0281       enable_if_t<
0282         traits::static_query<T, allowed_t>::is_valid
0283       >* = 0) noexcept
0284   {
0285     return traits::static_query<T, allowed_t>::value();
0286   }
0287 
0288   template <typename E,
0289       typename T = decltype(blocking_adaptation_t::static_query<E>())>
0290   static constexpr const T static_query_v
0291     = blocking_adaptation_t::static_query<E>();
0292 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
0293        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
0294 
0295   friend constexpr bool operator==(
0296       const blocking_adaptation_t& a, const blocking_adaptation_t& b)
0297   {
0298     return a.value_ == b.value_;
0299   }
0300 
0301   friend constexpr bool operator!=(
0302       const blocking_adaptation_t& a, const blocking_adaptation_t& b)
0303   {
0304     return a.value_ != b.value_;
0305   }
0306 
0307   struct convertible_from_blocking_adaptation_t
0308   {
0309     constexpr convertible_from_blocking_adaptation_t(
0310         blocking_adaptation_t)
0311     {
0312     }
0313   };
0314 
0315   template <typename Executor>
0316   friend constexpr blocking_adaptation_t query(
0317       const Executor& ex, convertible_from_blocking_adaptation_t,
0318       enable_if_t<
0319         can_query<const Executor&, disallowed_t>::value
0320       >* = 0)
0321 #if !defined(__clang__) // Clang crashes if noexcept is used here.
0322 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
0323     noexcept(is_nothrow_query<const Executor&,
0324         blocking_adaptation_t<>::disallowed_t>::value)
0325 #else // defined(BOOST_ASIO_MSVC)
0326     noexcept(is_nothrow_query<const Executor&, disallowed_t>::value)
0327 #endif // defined(BOOST_ASIO_MSVC)
0328 #endif // !defined(__clang__)
0329   {
0330     return boost::asio::query(ex, disallowed_t());
0331   }
0332 
0333   template <typename Executor>
0334   friend constexpr blocking_adaptation_t query(
0335       const Executor& ex, convertible_from_blocking_adaptation_t,
0336       enable_if_t<
0337         !can_query<const Executor&, disallowed_t>::value
0338       >* = 0,
0339       enable_if_t<
0340         can_query<const Executor&, allowed_t>::value
0341       >* = 0)
0342 #if !defined(__clang__) // Clang crashes if noexcept is used here.
0343 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
0344     noexcept(is_nothrow_query<const Executor&,
0345         blocking_adaptation_t<>::allowed_t>::value)
0346 #else // defined(BOOST_ASIO_MSVC)
0347     noexcept(is_nothrow_query<const Executor&, allowed_t>::value)
0348 #endif // defined(BOOST_ASIO_MSVC)
0349 #endif // !defined(__clang__)
0350   {
0351     return boost::asio::query(ex, allowed_t());
0352   }
0353 
0354   BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(disallowed_t, disallowed);
0355   BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(allowed_t, allowed);
0356 
0357 private:
0358   int value_;
0359 };
0360 
0361 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
0362   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
0363 template <int I> template <typename E, typename T>
0364 const T blocking_adaptation_t<I>::static_query_v;
0365 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
0366        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
0367 
0368 template <int I>
0369 const typename blocking_adaptation_t<I>::disallowed_t
0370 blocking_adaptation_t<I>::disallowed;
0371 
0372 template <int I>
0373 const typename blocking_adaptation_t<I>::allowed_t
0374 blocking_adaptation_t<I>::allowed;
0375 
0376 namespace blocking_adaptation {
0377 
0378 template <int I = 0>
0379 struct disallowed_t
0380 {
0381 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
0382   template <typename T>
0383   static constexpr bool is_applicable_property_v = is_executor<T>::value;
0384 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
0385 
0386   static constexpr bool is_requirable = true;
0387   static constexpr bool is_preferable = true;
0388   typedef blocking_adaptation_t<I> polymorphic_query_result_type;
0389 
0390   constexpr disallowed_t()
0391   {
0392   }
0393 
0394   template <typename T>
0395   struct query_member :
0396     traits::query_member<
0397       typename blocking_adaptation_t<I>::template proxy<T>::type,
0398         disallowed_t> {};
0399 
0400   template <typename T>
0401   struct query_static_constexpr_member :
0402     traits::query_static_constexpr_member<
0403       typename blocking_adaptation_t<I>::template static_proxy<T>::type,
0404         disallowed_t> {};
0405 
0406 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
0407   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
0408   template <typename T>
0409   static constexpr
0410   typename query_static_constexpr_member<T>::result_type
0411   static_query()
0412     noexcept(query_static_constexpr_member<T>::is_noexcept)
0413   {
0414     return query_static_constexpr_member<T>::value();
0415   }
0416 
0417   template <typename T>
0418   static constexpr disallowed_t static_query(
0419       enable_if_t<
0420         !query_static_constexpr_member<T>::is_valid
0421       >* = 0,
0422       enable_if_t<
0423         !query_member<T>::is_valid
0424       >* = 0,
0425       enable_if_t<
0426         !traits::query_free<T, disallowed_t>::is_valid
0427       >* = 0,
0428       enable_if_t<
0429         !can_query<T, allowed_t<I>>::value
0430       >* = 0) noexcept
0431   {
0432     return disallowed_t();
0433   }
0434 
0435   template <typename E, typename T = decltype(disallowed_t::static_query<E>())>
0436   static constexpr const T static_query_v
0437     = disallowed_t::static_query<E>();
0438 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
0439        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
0440 
0441   static constexpr blocking_adaptation_t<I> value()
0442   {
0443     return disallowed_t();
0444   }
0445 
0446   friend constexpr bool operator==(const disallowed_t&, const disallowed_t&)
0447   {
0448     return true;
0449   }
0450 
0451   friend constexpr bool operator!=(const disallowed_t&, const disallowed_t&)
0452   {
0453     return false;
0454   }
0455 
0456   friend constexpr bool operator==(const disallowed_t&, const allowed_t<I>&)
0457   {
0458     return false;
0459   }
0460 
0461   friend constexpr bool operator!=(const disallowed_t&, const allowed_t<I>&)
0462   {
0463     return true;
0464   }
0465 };
0466 
0467 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
0468   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
0469 template <int I> template <typename E, typename T>
0470 const T disallowed_t<I>::static_query_v;
0471 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
0472        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
0473 
0474 template <typename>
0475 struct is_blocking_adaptation_t : false_type
0476 {
0477 };
0478 
0479 template <int I>
0480 struct is_blocking_adaptation_t<blocking_adaptation_t<I>> : true_type
0481 {
0482 };
0483 
0484 template <typename>
0485 struct is_allowed_t : false_type
0486 {
0487 };
0488 
0489 template <int I>
0490 struct is_allowed_t<allowed_t<I>> : true_type
0491 {
0492 };
0493 
0494 template <typename>
0495 struct is_disallowed_t : false_type
0496 {
0497 };
0498 
0499 template <int I>
0500 struct is_disallowed_t<disallowed_t<I>> : true_type
0501 {
0502 };
0503 
0504 template <typename Executor>
0505 class adapter
0506 {
0507 public:
0508   adapter(int, const Executor& e) noexcept
0509     : executor_(e)
0510   {
0511   }
0512 
0513   adapter(const adapter& other) noexcept
0514     : executor_(other.executor_)
0515   {
0516   }
0517 
0518   adapter(adapter&& other) noexcept
0519     : executor_(static_cast<Executor&&>(other.executor_))
0520   {
0521   }
0522 
0523   template <int I>
0524   static constexpr allowed_t<I> query(blocking_adaptation_t<I>) noexcept
0525   {
0526     return allowed_t<I>();
0527   }
0528 
0529   template <int I>
0530   static constexpr allowed_t<I> query(allowed_t<I>) noexcept
0531   {
0532     return allowed_t<I>();
0533   }
0534 
0535   template <int I>
0536   static constexpr allowed_t<I> query(disallowed_t<I>) noexcept
0537   {
0538     return allowed_t<I>();
0539   }
0540 
0541   template <typename Property>
0542   enable_if_t<
0543     can_query<const Executor&, Property>::value
0544       && !is_blocking_adaptation_t<Property>::value
0545       && !is_allowed_t<Property>::value
0546       && !is_disallowed_t<Property>::value,
0547     query_result_t<const Executor&, Property>
0548   > query(const Property& p) const
0549     noexcept(is_nothrow_query<const Executor&, Property>::value)
0550   {
0551     return boost::asio::query(executor_, p);
0552   }
0553 
0554   template <int I>
0555   Executor require(disallowed_t<I>) const noexcept
0556   {
0557     return executor_;
0558   }
0559 
0560   template <typename Property>
0561   enable_if_t<
0562     can_require<const Executor&, Property>::value
0563       && !is_blocking_adaptation_t<Property>::value
0564       && !is_allowed_t<Property>::value
0565       && !is_disallowed_t<Property>::value,
0566     adapter<decay_t<require_result_t<const Executor&, Property>>>
0567   > require(const Property& p) const
0568     noexcept(is_nothrow_require<const Executor&, Property>::value)
0569   {
0570     return adapter<decay_t<require_result_t<const Executor&, Property>>>(
0571         0, boost::asio::require(executor_, p));
0572   }
0573 
0574   template <typename Property>
0575   enable_if_t<
0576     can_prefer<const Executor&, Property>::value
0577       && !is_blocking_adaptation_t<Property>::value
0578       && !is_allowed_t<Property>::value
0579       && !is_disallowed_t<Property>::value,
0580     adapter<decay_t<prefer_result_t<const Executor&, Property>>>
0581   > prefer(const Property& p) const
0582     noexcept(is_nothrow_prefer<const Executor&, Property>::value)
0583   {
0584     return adapter<decay_t<prefer_result_t<const Executor&, Property>>>(
0585         0, boost::asio::prefer(executor_, p));
0586   }
0587 
0588   template <typename Function>
0589   enable_if_t<
0590     traits::execute_member<const Executor&, Function>::is_valid
0591   > execute(Function&& f) const
0592   {
0593     executor_.execute(static_cast<Function&&>(f));
0594   }
0595 
0596   friend bool operator==(const adapter& a, const adapter& b) noexcept
0597   {
0598     return a.executor_ == b.executor_;
0599   }
0600 
0601   friend bool operator!=(const adapter& a, const adapter& b) noexcept
0602   {
0603     return a.executor_ != b.executor_;
0604   }
0605 
0606 private:
0607   Executor executor_;
0608 };
0609 
0610 template <int I = 0>
0611 struct allowed_t
0612 {
0613 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
0614   template <typename T>
0615   static constexpr bool is_applicable_property_v = is_executor<T>::value;
0616 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
0617 
0618   static constexpr bool is_requirable = true;
0619   static constexpr bool is_preferable = false;
0620   typedef blocking_adaptation_t<I> polymorphic_query_result_type;
0621 
0622   constexpr allowed_t()
0623   {
0624   }
0625 
0626   template <typename T>
0627   struct query_member :
0628     traits::query_member<
0629       typename blocking_adaptation_t<I>::template proxy<T>::type,
0630         allowed_t> {};
0631 
0632   template <typename T>
0633   struct query_static_constexpr_member :
0634     traits::query_static_constexpr_member<
0635       typename blocking_adaptation_t<I>::template static_proxy<T>::type,
0636         allowed_t> {};
0637 
0638 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
0639   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
0640   template <typename T>
0641   static constexpr typename query_static_constexpr_member<T>::result_type
0642   static_query()
0643     noexcept(query_static_constexpr_member<T>::is_noexcept)
0644   {
0645     return query_static_constexpr_member<T>::value();
0646   }
0647 
0648   template <typename E, typename T = decltype(allowed_t::static_query<E>())>
0649   static constexpr const T static_query_v = allowed_t::static_query<E>();
0650 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
0651        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
0652 
0653   static constexpr blocking_adaptation_t<I> value()
0654   {
0655     return allowed_t();
0656   }
0657 
0658   friend constexpr bool operator==(const allowed_t&, const allowed_t&)
0659   {
0660     return true;
0661   }
0662 
0663   friend constexpr bool operator!=(const allowed_t&, const allowed_t&)
0664   {
0665     return false;
0666   }
0667 
0668   friend constexpr bool operator==(const allowed_t&, const disallowed_t<I>&)
0669   {
0670     return false;
0671   }
0672 
0673   friend constexpr bool operator!=(const allowed_t&, const disallowed_t<I>&)
0674   {
0675     return true;
0676   }
0677 
0678   template <typename Executor>
0679   friend adapter<Executor> require(
0680       const Executor& e, const allowed_t&,
0681       enable_if_t<
0682         is_executor<Executor>::value
0683       >* = 0)
0684   {
0685     return adapter<Executor>(0, e);
0686   }
0687 };
0688 
0689 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
0690   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
0691 template <int I> template <typename E, typename T>
0692 const T allowed_t<I>::static_query_v;
0693 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
0694        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
0695 
0696 template <typename Function>
0697 class blocking_execute_state
0698 {
0699 public:
0700   template <typename F>
0701   blocking_execute_state(F&& f)
0702     : func_(static_cast<F&&>(f)),
0703       is_complete_(false)
0704   {
0705   }
0706 
0707   template <typename Executor>
0708   void execute_and_wait(Executor&& ex)
0709   {
0710     handler h = { this };
0711     ex.execute(h);
0712     boost::asio::detail::mutex::scoped_lock lock(mutex_);
0713     while (!is_complete_)
0714       event_.wait(lock);
0715   }
0716 
0717   struct cleanup
0718   {
0719     ~cleanup()
0720     {
0721       boost::asio::detail::mutex::scoped_lock lock(state_->mutex_);
0722       state_->is_complete_ = true;
0723       state_->event_.unlock_and_signal_one_for_destruction(lock);
0724     }
0725 
0726     blocking_execute_state* state_;
0727   };
0728 
0729   struct handler
0730   {
0731     void operator()()
0732     {
0733       cleanup c = { state_ };
0734       state_->func_();
0735     }
0736 
0737     blocking_execute_state* state_;
0738   };
0739 
0740   Function func_;
0741   boost::asio::detail::mutex mutex_;
0742   boost::asio::detail::event event_;
0743   bool is_complete_;
0744 };
0745 
0746 template <typename Executor, typename Function>
0747 void blocking_execute(
0748     Executor&& ex,
0749     Function&& func)
0750 {
0751   typedef decay_t<Function> func_t;
0752   blocking_execute_state<func_t> state(static_cast<Function&&>(func));
0753   state.execute_and_wait(ex);
0754 }
0755 
0756 } // namespace blocking_adaptation
0757 } // namespace detail
0758 
0759 typedef detail::blocking_adaptation_t<> blocking_adaptation_t;
0760 
0761 BOOST_ASIO_INLINE_VARIABLE constexpr blocking_adaptation_t blocking_adaptation;
0762 
0763 } // namespace execution
0764 
0765 #if !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
0766 
0767 template <typename T>
0768 struct is_applicable_property<T, execution::blocking_adaptation_t>
0769   : integral_constant<bool, execution::is_executor<T>::value>
0770 {
0771 };
0772 
0773 template <typename T>
0774 struct is_applicable_property<T, execution::blocking_adaptation_t::disallowed_t>
0775   : integral_constant<bool, execution::is_executor<T>::value>
0776 {
0777 };
0778 
0779 template <typename T>
0780 struct is_applicable_property<T, execution::blocking_adaptation_t::allowed_t>
0781   : integral_constant<bool, execution::is_executor<T>::value>
0782 {
0783 };
0784 
0785 #endif // !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
0786 
0787 namespace traits {
0788 
0789 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
0790 
0791 template <typename T>
0792 struct query_free_default<T, execution::blocking_adaptation_t,
0793   enable_if_t<
0794     can_query<T, execution::blocking_adaptation_t::disallowed_t>::value
0795   >>
0796 {
0797   static constexpr bool is_valid = true;
0798   static constexpr bool is_noexcept =
0799     is_nothrow_query<T, execution::blocking_adaptation_t::disallowed_t>::value;
0800 
0801   typedef execution::blocking_adaptation_t result_type;
0802 };
0803 
0804 template <typename T>
0805 struct query_free_default<T, execution::blocking_adaptation_t,
0806   enable_if_t<
0807     !can_query<T, execution::blocking_adaptation_t::disallowed_t>::value
0808       && can_query<T, execution::blocking_adaptation_t::allowed_t>::value
0809   >>
0810 {
0811   static constexpr bool is_valid = true;
0812   static constexpr bool is_noexcept =
0813     is_nothrow_query<T, execution::blocking_adaptation_t::allowed_t>::value;
0814 
0815   typedef execution::blocking_adaptation_t result_type;
0816 };
0817 
0818 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
0819 
0820 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
0821   || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
0822 
0823 template <typename T>
0824 struct static_query<T, execution::blocking_adaptation_t,
0825   enable_if_t<
0826     execution::detail::blocking_adaptation_t<0>::
0827       query_static_constexpr_member<T>::is_valid
0828   >>
0829 {
0830   static constexpr bool is_valid = true;
0831   static constexpr bool is_noexcept = true;
0832 
0833   typedef typename execution::detail::blocking_adaptation_t<0>::
0834     query_static_constexpr_member<T>::result_type result_type;
0835 
0836   static constexpr result_type value()
0837   {
0838     return execution::detail::blocking_adaptation_t<0>::
0839       query_static_constexpr_member<T>::value();
0840   }
0841 };
0842 
0843 template <typename T>
0844 struct static_query<T, execution::blocking_adaptation_t,
0845   enable_if_t<
0846     !execution::detail::blocking_adaptation_t<0>::
0847         query_static_constexpr_member<T>::is_valid
0848       && !execution::detail::blocking_adaptation_t<0>::
0849         query_member<T>::is_valid
0850       && traits::static_query<T,
0851         execution::blocking_adaptation_t::disallowed_t>::is_valid
0852   >>
0853 {
0854   static constexpr bool is_valid = true;
0855   static constexpr bool is_noexcept = true;
0856 
0857   typedef typename traits::static_query<T,
0858     execution::blocking_adaptation_t::disallowed_t>::result_type result_type;
0859 
0860   static constexpr result_type value()
0861   {
0862     return traits::static_query<T,
0863         execution::blocking_adaptation_t::disallowed_t>::value();
0864   }
0865 };
0866 
0867 template <typename T>
0868 struct static_query<T, execution::blocking_adaptation_t,
0869   enable_if_t<
0870     !execution::detail::blocking_adaptation_t<0>::
0871         query_static_constexpr_member<T>::is_valid
0872       && !execution::detail::blocking_adaptation_t<0>::
0873         query_member<T>::is_valid
0874       && !traits::static_query<T,
0875         execution::blocking_adaptation_t::disallowed_t>::is_valid
0876       && traits::static_query<T,
0877         execution::blocking_adaptation_t::allowed_t>::is_valid
0878   >>
0879 {
0880   static constexpr bool is_valid = true;
0881   static constexpr bool is_noexcept = true;
0882 
0883   typedef typename traits::static_query<T,
0884     execution::blocking_adaptation_t::allowed_t>::result_type result_type;
0885 
0886   static constexpr result_type value()
0887   {
0888     return traits::static_query<T,
0889         execution::blocking_adaptation_t::allowed_t>::value();
0890   }
0891 };
0892 
0893 template <typename T>
0894 struct static_query<T, execution::blocking_adaptation_t::disallowed_t,
0895   enable_if_t<
0896     execution::detail::blocking_adaptation::disallowed_t<0>::
0897       query_static_constexpr_member<T>::is_valid
0898   >>
0899 {
0900   static constexpr bool is_valid = true;
0901   static constexpr bool is_noexcept = true;
0902 
0903   typedef typename execution::detail::blocking_adaptation::disallowed_t<0>::
0904     query_static_constexpr_member<T>::result_type result_type;
0905 
0906   static constexpr result_type value()
0907   {
0908     return execution::detail::blocking_adaptation::disallowed_t<0>::
0909       query_static_constexpr_member<T>::value();
0910   }
0911 };
0912 
0913 template <typename T>
0914 struct static_query<T, execution::blocking_adaptation_t::disallowed_t,
0915   enable_if_t<
0916     !execution::detail::blocking_adaptation::disallowed_t<0>::
0917         query_static_constexpr_member<T>::is_valid
0918       && !execution::detail::blocking_adaptation::disallowed_t<0>::
0919         query_member<T>::is_valid
0920       && !traits::query_free<T,
0921         execution::blocking_adaptation_t::disallowed_t>::is_valid
0922       && !can_query<T, execution::blocking_adaptation_t::allowed_t>::value
0923   >>
0924 {
0925   static constexpr bool is_valid = true;
0926   static constexpr bool is_noexcept = true;
0927 
0928   typedef execution::blocking_adaptation_t::disallowed_t result_type;
0929 
0930   static constexpr result_type value()
0931   {
0932     return result_type();
0933   }
0934 };
0935 
0936 template <typename T>
0937 struct static_query<T, execution::blocking_adaptation_t::allowed_t,
0938   enable_if_t<
0939     execution::detail::blocking_adaptation::allowed_t<0>::
0940       query_static_constexpr_member<T>::is_valid
0941   >>
0942 {
0943   static constexpr bool is_valid = true;
0944   static constexpr bool is_noexcept = true;
0945 
0946   typedef typename execution::detail::blocking_adaptation::allowed_t<0>::
0947     query_static_constexpr_member<T>::result_type result_type;
0948 
0949   static constexpr result_type value()
0950   {
0951     return execution::detail::blocking_adaptation::allowed_t<0>::
0952       query_static_constexpr_member<T>::value();
0953   }
0954 };
0955 
0956 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
0957        //   || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
0958 
0959 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT)
0960 
0961 template <typename T>
0962 struct require_free_default<T, execution::blocking_adaptation_t::allowed_t,
0963   enable_if_t<
0964     is_same<T, decay_t<T>>::value
0965       && execution::is_executor<T>::value
0966   >>
0967 {
0968   static constexpr bool is_valid = true;
0969   static constexpr bool is_noexcept = false;
0970   typedef execution::detail::blocking_adaptation::adapter<T> result_type;
0971 };
0972 
0973 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT)
0974 
0975 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
0976 
0977 template <typename Executor>
0978 struct equality_comparable<
0979   execution::detail::blocking_adaptation::adapter<Executor>>
0980 {
0981   static constexpr bool is_valid = true;
0982   static constexpr bool is_noexcept = true;
0983 };
0984 
0985 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
0986 
0987 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
0988 
0989 template <typename Executor, typename Function>
0990 struct execute_member<
0991   execution::detail::blocking_adaptation::adapter<Executor>, Function>
0992 {
0993   static constexpr bool is_valid = true;
0994   static constexpr bool is_noexcept = false;
0995   typedef void result_type;
0996 };
0997 
0998 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
0999 
1000 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
1001 
1002 template <typename Executor, int I>
1003 struct query_static_constexpr_member<
1004   execution::detail::blocking_adaptation::adapter<Executor>,
1005   execution::detail::blocking_adaptation_t<I>>
1006 {
1007   static constexpr bool is_valid = true;
1008   static constexpr bool is_noexcept = true;
1009   typedef execution::blocking_adaptation_t::allowed_t result_type;
1010 
1011   static constexpr result_type value() noexcept
1012   {
1013     return result_type();
1014   }
1015 };
1016 
1017 template <typename Executor, int I>
1018 struct query_static_constexpr_member<
1019   execution::detail::blocking_adaptation::adapter<Executor>,
1020   execution::detail::blocking_adaptation::allowed_t<I>>
1021 {
1022   static constexpr bool is_valid = true;
1023   static constexpr bool is_noexcept = true;
1024   typedef execution::blocking_adaptation_t::allowed_t result_type;
1025 
1026   static constexpr result_type value() noexcept
1027   {
1028     return result_type();
1029   }
1030 };
1031 
1032 template <typename Executor, int I>
1033 struct query_static_constexpr_member<
1034   execution::detail::blocking_adaptation::adapter<Executor>,
1035   execution::detail::blocking_adaptation::disallowed_t<I>>
1036 {
1037   static constexpr bool is_valid = true;
1038   static constexpr bool is_noexcept = true;
1039   typedef execution::blocking_adaptation_t::allowed_t result_type;
1040 
1041   static constexpr result_type value() noexcept
1042   {
1043     return result_type();
1044   }
1045 };
1046 
1047 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
1048 
1049 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
1050 
1051 template <typename Executor, typename Property>
1052 struct query_member<
1053   execution::detail::blocking_adaptation::adapter<Executor>, Property,
1054   enable_if_t<
1055     can_query<const Executor&, Property>::value
1056   >>
1057 {
1058   static constexpr bool is_valid = true;
1059   static constexpr bool is_noexcept =
1060     is_nothrow_query<Executor, Property>::value;
1061   typedef query_result_t<Executor, Property> result_type;
1062 };
1063 
1064 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
1065 
1066 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
1067 
1068 template <typename Executor, int I>
1069 struct require_member<
1070   execution::detail::blocking_adaptation::adapter<Executor>,
1071   execution::detail::blocking_adaptation::disallowed_t<I>>
1072 {
1073   static constexpr bool is_valid = true;
1074   static constexpr bool is_noexcept = true;
1075   typedef Executor result_type;
1076 };
1077 
1078 template <typename Executor, typename Property>
1079 struct require_member<
1080   execution::detail::blocking_adaptation::adapter<Executor>, Property,
1081   enable_if_t<
1082     can_require<const Executor&, Property>::value
1083   >>
1084 {
1085   static constexpr bool is_valid = true;
1086   static constexpr bool is_noexcept =
1087     is_nothrow_require<Executor, Property>::value;
1088   typedef execution::detail::blocking_adaptation::adapter<
1089     decay_t<require_result_t<Executor, Property>>> result_type;
1090 };
1091 
1092 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
1093 
1094 #if !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
1095 
1096 template <typename Executor, typename Property>
1097 struct prefer_member<
1098   execution::detail::blocking_adaptation::adapter<Executor>, Property,
1099   enable_if_t<
1100     can_prefer<const Executor&, Property>::value
1101   >>
1102 {
1103   static constexpr bool is_valid = true;
1104   static constexpr bool is_noexcept =
1105     is_nothrow_prefer<Executor, Property>::value;
1106   typedef execution::detail::blocking_adaptation::adapter<
1107     decay_t<prefer_result_t<Executor, Property>>> result_type;
1108 };
1109 
1110 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
1111 
1112 } // namespace traits
1113 
1114 #endif // defined(GENERATING_DOCUMENTATION)
1115 
1116 } // namespace asio
1117 } // namespace boost
1118 
1119 #include <boost/asio/detail/pop_options.hpp>
1120 
1121 #endif // BOOST_ASIO_EXECUTION_BLOCKING_ADAPTATION_HPP