Back to home page

EIC code displayed by LXR

 
 

    


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

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