Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-15 08:28:37

0001 //
0002 // bind_immediate_executor.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2024 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_BIND_IMMEDIATE_EXECUTOR_HPP
0012 #define BOOST_ASIO_BIND_IMMEDIATE_EXECUTOR_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/associated_executor.hpp>
0020 #include <boost/asio/associated_immediate_executor.hpp>
0021 #include <boost/asio/associator.hpp>
0022 #include <boost/asio/async_result.hpp>
0023 #include <boost/asio/detail/initiation_base.hpp>
0024 #include <boost/asio/detail/type_traits.hpp>
0025 
0026 #include <boost/asio/detail/push_options.hpp>
0027 
0028 namespace boost {
0029 namespace asio {
0030 namespace detail {
0031 
0032 // Helper to automatically define nested typedef result_type.
0033 
0034 template <typename T, typename = void>
0035 struct immediate_executor_binder_result_type
0036 {
0037 protected:
0038   typedef void result_type_or_void;
0039 };
0040 
0041 template <typename T>
0042 struct immediate_executor_binder_result_type<T, void_t<typename T::result_type>>
0043 {
0044   typedef typename T::result_type result_type;
0045 protected:
0046   typedef result_type result_type_or_void;
0047 };
0048 
0049 template <typename R>
0050 struct immediate_executor_binder_result_type<R(*)()>
0051 {
0052   typedef R result_type;
0053 protected:
0054   typedef result_type result_type_or_void;
0055 };
0056 
0057 template <typename R>
0058 struct immediate_executor_binder_result_type<R(&)()>
0059 {
0060   typedef R result_type;
0061 protected:
0062   typedef result_type result_type_or_void;
0063 };
0064 
0065 template <typename R, typename A1>
0066 struct immediate_executor_binder_result_type<R(*)(A1)>
0067 {
0068   typedef R result_type;
0069 protected:
0070   typedef result_type result_type_or_void;
0071 };
0072 
0073 template <typename R, typename A1>
0074 struct immediate_executor_binder_result_type<R(&)(A1)>
0075 {
0076   typedef R result_type;
0077 protected:
0078   typedef result_type result_type_or_void;
0079 };
0080 
0081 template <typename R, typename A1, typename A2>
0082 struct immediate_executor_binder_result_type<R(*)(A1, A2)>
0083 {
0084   typedef R result_type;
0085 protected:
0086   typedef result_type result_type_or_void;
0087 };
0088 
0089 template <typename R, typename A1, typename A2>
0090 struct immediate_executor_binder_result_type<R(&)(A1, A2)>
0091 {
0092   typedef R result_type;
0093 protected:
0094   typedef result_type result_type_or_void;
0095 };
0096 
0097 // Helper to automatically define nested typedef argument_type.
0098 
0099 template <typename T, typename = void>
0100 struct immediate_executor_binder_argument_type {};
0101 
0102 template <typename T>
0103 struct immediate_executor_binder_argument_type<T,
0104   void_t<typename T::argument_type>>
0105 {
0106   typedef typename T::argument_type argument_type;
0107 };
0108 
0109 template <typename R, typename A1>
0110 struct immediate_executor_binder_argument_type<R(*)(A1)>
0111 {
0112   typedef A1 argument_type;
0113 };
0114 
0115 template <typename R, typename A1>
0116 struct immediate_executor_binder_argument_type<R(&)(A1)>
0117 {
0118   typedef A1 argument_type;
0119 };
0120 
0121 // Helper to automatically define nested typedefs first_argument_type and
0122 // second_argument_type.
0123 
0124 template <typename T, typename = void>
0125 struct immediate_executor_binder_argument_types {};
0126 
0127 template <typename T>
0128 struct immediate_executor_binder_argument_types<T,
0129   void_t<typename T::first_argument_type>>
0130 {
0131   typedef typename T::first_argument_type first_argument_type;
0132   typedef typename T::second_argument_type second_argument_type;
0133 };
0134 
0135 template <typename R, typename A1, typename A2>
0136 struct immediate_executor_binder_argument_type<R(*)(A1, A2)>
0137 {
0138   typedef A1 first_argument_type;
0139   typedef A2 second_argument_type;
0140 };
0141 
0142 template <typename R, typename A1, typename A2>
0143 struct immediate_executor_binder_argument_type<R(&)(A1, A2)>
0144 {
0145   typedef A1 first_argument_type;
0146   typedef A2 second_argument_type;
0147 };
0148 
0149 } // namespace detail
0150 
0151 /// A call wrapper type to bind a immediate executor of type @c Executor
0152 /// to an object of type @c T.
0153 template <typename T, typename Executor>
0154 class immediate_executor_binder
0155 #if !defined(GENERATING_DOCUMENTATION)
0156   : public detail::immediate_executor_binder_result_type<T>,
0157     public detail::immediate_executor_binder_argument_type<T>,
0158     public detail::immediate_executor_binder_argument_types<T>
0159 #endif // !defined(GENERATING_DOCUMENTATION)
0160 {
0161 public:
0162   /// The type of the target object.
0163   typedef T target_type;
0164 
0165   /// The type of the associated immediate executor.
0166   typedef Executor immediate_executor_type;
0167 
0168 #if defined(GENERATING_DOCUMENTATION)
0169   /// The return type if a function.
0170   /**
0171    * The type of @c result_type is based on the type @c T of the wrapper's
0172    * target object:
0173    *
0174    * @li if @c T is a pointer to function type, @c result_type is a synonym for
0175    * the return type of @c T;
0176    *
0177    * @li if @c T is a class type with a member type @c result_type, then @c
0178    * result_type is a synonym for @c T::result_type;
0179    *
0180    * @li otherwise @c result_type is not defined.
0181    */
0182   typedef see_below result_type;
0183 
0184   /// The type of the function's argument.
0185   /**
0186    * The type of @c argument_type is based on the type @c T of the wrapper's
0187    * target object:
0188    *
0189    * @li if @c T is a pointer to a function type accepting a single argument,
0190    * @c argument_type is a synonym for the return type of @c T;
0191    *
0192    * @li if @c T is a class type with a member type @c argument_type, then @c
0193    * argument_type is a synonym for @c T::argument_type;
0194    *
0195    * @li otherwise @c argument_type is not defined.
0196    */
0197   typedef see_below argument_type;
0198 
0199   /// The type of the function's first argument.
0200   /**
0201    * The type of @c first_argument_type is based on the type @c T of the
0202    * wrapper's target object:
0203    *
0204    * @li if @c T is a pointer to a function type accepting two arguments, @c
0205    * first_argument_type is a synonym for the return type of @c T;
0206    *
0207    * @li if @c T is a class type with a member type @c first_argument_type,
0208    * then @c first_argument_type is a synonym for @c T::first_argument_type;
0209    *
0210    * @li otherwise @c first_argument_type is not defined.
0211    */
0212   typedef see_below first_argument_type;
0213 
0214   /// The type of the function's second argument.
0215   /**
0216    * The type of @c second_argument_type is based on the type @c T of the
0217    * wrapper's target object:
0218    *
0219    * @li if @c T is a pointer to a function type accepting two arguments, @c
0220    * second_argument_type is a synonym for the return type of @c T;
0221    *
0222    * @li if @c T is a class type with a member type @c first_argument_type,
0223    * then @c second_argument_type is a synonym for @c T::second_argument_type;
0224    *
0225    * @li otherwise @c second_argument_type is not defined.
0226    */
0227   typedef see_below second_argument_type;
0228 #endif // defined(GENERATING_DOCUMENTATION)
0229 
0230   /// Construct a immediate executor wrapper for the specified object.
0231   /**
0232    * This constructor is only valid if the type @c T is constructible from type
0233    * @c U.
0234    */
0235   template <typename U>
0236   immediate_executor_binder(const immediate_executor_type& e,
0237       U&& u)
0238     : executor_(e),
0239       target_(static_cast<U&&>(u))
0240   {
0241   }
0242 
0243   /// Copy constructor.
0244   immediate_executor_binder(const immediate_executor_binder& other)
0245     : executor_(other.get_immediate_executor()),
0246       target_(other.get())
0247   {
0248   }
0249 
0250   /// Construct a copy, but specify a different immediate executor.
0251   immediate_executor_binder(const immediate_executor_type& e,
0252       const immediate_executor_binder& other)
0253     : executor_(e),
0254       target_(other.get())
0255   {
0256   }
0257 
0258   /// Construct a copy of a different immediate executor wrapper type.
0259   /**
0260    * This constructor is only valid if the @c Executor type is
0261    * constructible from type @c OtherExecutor, and the type @c T is
0262    * constructible from type @c U.
0263    */
0264   template <typename U, typename OtherExecutor>
0265   immediate_executor_binder(
0266       const immediate_executor_binder<U, OtherExecutor>& other,
0267       constraint_t<is_constructible<Executor, OtherExecutor>::value> = 0,
0268       constraint_t<is_constructible<T, U>::value> = 0)
0269     : executor_(other.get_immediate_executor()),
0270       target_(other.get())
0271   {
0272   }
0273 
0274   /// Construct a copy of a different immediate executor wrapper type, but
0275   /// specify a different immediate executor.
0276   /**
0277    * This constructor is only valid if the type @c T is constructible from type
0278    * @c U.
0279    */
0280   template <typename U, typename OtherExecutor>
0281   immediate_executor_binder(const immediate_executor_type& e,
0282       const immediate_executor_binder<U, OtherExecutor>& other,
0283       constraint_t<is_constructible<T, U>::value> = 0)
0284     : executor_(e),
0285       target_(other.get())
0286   {
0287   }
0288 
0289   /// Move constructor.
0290   immediate_executor_binder(immediate_executor_binder&& other)
0291     : executor_(static_cast<immediate_executor_type&&>(
0292           other.get_immediate_executor())),
0293       target_(static_cast<T&&>(other.get()))
0294   {
0295   }
0296 
0297   /// Move construct the target object, but specify a different immediate
0298   /// executor.
0299   immediate_executor_binder(const immediate_executor_type& e,
0300       immediate_executor_binder&& other)
0301     : executor_(e),
0302       target_(static_cast<T&&>(other.get()))
0303   {
0304   }
0305 
0306   /// Move construct from a different immediate executor wrapper type.
0307   template <typename U, typename OtherExecutor>
0308   immediate_executor_binder(
0309       immediate_executor_binder<U, OtherExecutor>&& other,
0310       constraint_t<is_constructible<Executor, OtherExecutor>::value> = 0,
0311       constraint_t<is_constructible<T, U>::value> = 0)
0312     : executor_(static_cast<OtherExecutor&&>(
0313           other.get_immediate_executor())),
0314       target_(static_cast<U&&>(other.get()))
0315   {
0316   }
0317 
0318   /// Move construct from a different immediate executor wrapper type, but
0319   /// specify a different immediate executor.
0320   template <typename U, typename OtherExecutor>
0321   immediate_executor_binder(const immediate_executor_type& e,
0322       immediate_executor_binder<U, OtherExecutor>&& other,
0323       constraint_t<is_constructible<T, U>::value> = 0)
0324     : executor_(e),
0325       target_(static_cast<U&&>(other.get()))
0326   {
0327   }
0328 
0329   /// Destructor.
0330   ~immediate_executor_binder()
0331   {
0332   }
0333 
0334   /// Obtain a reference to the target object.
0335   target_type& get() noexcept
0336   {
0337     return target_;
0338   }
0339 
0340   /// Obtain a reference to the target object.
0341   const target_type& get() const noexcept
0342   {
0343     return target_;
0344   }
0345 
0346   /// Obtain the associated immediate executor.
0347   immediate_executor_type get_immediate_executor() const noexcept
0348   {
0349     return executor_;
0350   }
0351 
0352   /// Forwarding function call operator.
0353   template <typename... Args>
0354   result_of_t<T(Args...)> operator()(Args&&... args)
0355   {
0356     return target_(static_cast<Args&&>(args)...);
0357   }
0358 
0359   /// Forwarding function call operator.
0360   template <typename... Args>
0361   result_of_t<T(Args...)> operator()(Args&&... args) const
0362   {
0363     return target_(static_cast<Args&&>(args)...);
0364   }
0365 
0366 private:
0367   Executor executor_;
0368   T target_;
0369 };
0370 
0371 /// A function object type that adapts a @ref completion_token to specify that
0372 /// the completion handler should have the supplied executor as its associated
0373 /// immediate executor.
0374 /**
0375  * May also be used directly as a completion token, in which case it adapts the
0376  * asynchronous operation's default completion token (or boost::asio::deferred
0377  * if no default is available).
0378  */
0379 template <typename Executor>
0380 struct partial_immediate_executor_binder
0381 {
0382   /// Constructor that specifies associated executor.
0383   explicit partial_immediate_executor_binder(const Executor& ex)
0384     : executor_(ex)
0385   {
0386   }
0387 
0388   /// Adapt a @ref completion_token to specify that the completion handler
0389   /// should have the executor as its associated immediate executor.
0390   template <typename CompletionToken>
0391   BOOST_ASIO_NODISCARD inline
0392   constexpr immediate_executor_binder<decay_t<CompletionToken>, Executor>
0393   operator()(CompletionToken&& completion_token) const
0394   {
0395     return immediate_executor_binder<decay_t<CompletionToken>, Executor>(
0396         static_cast<CompletionToken&&>(completion_token), executor_);
0397   }
0398 
0399 //private:
0400   Executor executor_;
0401 };
0402 
0403 /// Create a partial completion token that associates an executor.
0404 template <typename Executor>
0405 BOOST_ASIO_NODISCARD inline partial_immediate_executor_binder<Executor>
0406 bind_immediate_executor(const Executor& ex)
0407 {
0408   return partial_immediate_executor_binder<Executor>(ex);
0409 }
0410 
0411 /// Associate an object of type @c T with a immediate executor of type
0412 /// @c Executor.
0413 template <typename Executor, typename T>
0414 BOOST_ASIO_NODISCARD inline immediate_executor_binder<decay_t<T>, Executor>
0415 bind_immediate_executor(const Executor& e, T&& t)
0416 {
0417   return immediate_executor_binder<
0418     decay_t<T>, Executor>(
0419       e, static_cast<T&&>(t));
0420 }
0421 
0422 #if !defined(GENERATING_DOCUMENTATION)
0423 
0424 namespace detail {
0425 
0426 template <typename TargetAsyncResult, typename Executor, typename = void>
0427 class immediate_executor_binder_completion_handler_async_result
0428 {
0429 public:
0430   template <typename T>
0431   explicit immediate_executor_binder_completion_handler_async_result(T&)
0432   {
0433   }
0434 };
0435 
0436 template <typename TargetAsyncResult, typename Executor>
0437 class immediate_executor_binder_completion_handler_async_result<
0438   TargetAsyncResult, Executor,
0439   void_t<
0440     typename TargetAsyncResult::completion_handler_type
0441   >>
0442 {
0443 private:
0444   TargetAsyncResult target_;
0445 
0446 public:
0447   typedef immediate_executor_binder<
0448     typename TargetAsyncResult::completion_handler_type, Executor>
0449       completion_handler_type;
0450 
0451   explicit immediate_executor_binder_completion_handler_async_result(
0452       typename TargetAsyncResult::completion_handler_type& handler)
0453     : target_(handler)
0454   {
0455   }
0456 
0457   auto get() -> decltype(target_.get())
0458   {
0459     return target_.get();
0460   }
0461 };
0462 
0463 template <typename TargetAsyncResult, typename = void>
0464 struct immediate_executor_binder_async_result_return_type
0465 {
0466 };
0467 
0468 template <typename TargetAsyncResult>
0469 struct immediate_executor_binder_async_result_return_type<
0470   TargetAsyncResult,
0471   void_t<
0472     typename TargetAsyncResult::return_type
0473   >>
0474 {
0475   typedef typename TargetAsyncResult::return_type return_type;
0476 };
0477 
0478 } // namespace detail
0479 
0480 template <typename T, typename Executor, typename Signature>
0481 class async_result<immediate_executor_binder<T, Executor>, Signature> :
0482   public detail::immediate_executor_binder_completion_handler_async_result<
0483     async_result<T, Signature>, Executor>,
0484   public detail::immediate_executor_binder_async_result_return_type<
0485     async_result<T, Signature>>
0486 {
0487 public:
0488   explicit async_result(immediate_executor_binder<T, Executor>& b)
0489     : detail::immediate_executor_binder_completion_handler_async_result<
0490         async_result<T, Signature>, Executor>(b.get())
0491   {
0492   }
0493 
0494   template <typename Initiation>
0495   struct init_wrapper : detail::initiation_base<Initiation>
0496   {
0497     using detail::initiation_base<Initiation>::initiation_base;
0498 
0499     template <typename Handler, typename... Args>
0500     void operator()(Handler&& handler, const Executor& e, Args&&... args) &&
0501     {
0502       static_cast<Initiation&&>(*this)(
0503           immediate_executor_binder<
0504             decay_t<Handler>, Executor>(
0505               e, static_cast<Handler&&>(handler)),
0506           static_cast<Args&&>(args)...);
0507     }
0508 
0509     template <typename Handler, typename... Args>
0510     void operator()(Handler&& handler,
0511         const Executor& e, Args&&... args) const &
0512     {
0513       static_cast<const Initiation&>(*this)(
0514           immediate_executor_binder<
0515             decay_t<Handler>, Executor>(
0516               e, static_cast<Handler&&>(handler)),
0517           static_cast<Args&&>(args)...);
0518     }
0519   };
0520 
0521   template <typename Initiation, typename RawCompletionToken, typename... Args>
0522   static auto initiate(Initiation&& initiation,
0523       RawCompletionToken&& token, Args&&... args)
0524     -> decltype(
0525       async_initiate<
0526         conditional_t<
0527           is_const<remove_reference_t<RawCompletionToken>>::value, const T, T>,
0528         Signature>(
0529           declval<init_wrapper<decay_t<Initiation>>>(),
0530           token.get(), token.get_immediate_executor(),
0531           static_cast<Args&&>(args)...))
0532   {
0533     return async_initiate<
0534       conditional_t<
0535         is_const<remove_reference_t<RawCompletionToken>>::value, const T, T>,
0536       Signature>(
0537         init_wrapper<decay_t<Initiation>>(
0538           static_cast<Initiation&&>(initiation)),
0539         token.get(), token.get_immediate_executor(),
0540         static_cast<Args&&>(args)...);
0541   }
0542 
0543 private:
0544   async_result(const async_result&) = delete;
0545   async_result& operator=(const async_result&) = delete;
0546 
0547   async_result<T, Signature> target_;
0548 };
0549 
0550 template <typename Executor, typename... Signatures>
0551 struct async_result<partial_immediate_executor_binder<Executor>, Signatures...>
0552 {
0553   template <typename Initiation, typename RawCompletionToken, typename... Args>
0554   static auto initiate(Initiation&& initiation,
0555       RawCompletionToken&& token, Args&&... args)
0556     -> decltype(
0557       async_initiate<Signatures...>(
0558         static_cast<Initiation&&>(initiation),
0559         immediate_executor_binder<
0560           default_completion_token_t<associated_executor_t<Initiation>>,
0561           Executor>(token.executor_,
0562             default_completion_token_t<associated_executor_t<Initiation>>{}),
0563         static_cast<Args&&>(args)...))
0564   {
0565     return async_initiate<Signatures...>(
0566         static_cast<Initiation&&>(initiation),
0567         immediate_executor_binder<
0568           default_completion_token_t<associated_executor_t<Initiation>>,
0569           Executor>(token.executor_,
0570             default_completion_token_t<associated_executor_t<Initiation>>{}),
0571         static_cast<Args&&>(args)...);
0572   }
0573 };
0574 
0575 template <template <typename, typename> class Associator,
0576     typename T, typename Executor, typename DefaultCandidate>
0577 struct associator<Associator,
0578     immediate_executor_binder<T, Executor>,
0579     DefaultCandidate>
0580   : Associator<T, DefaultCandidate>
0581 {
0582   static typename Associator<T, DefaultCandidate>::type get(
0583       const immediate_executor_binder<T, Executor>& b) noexcept
0584   {
0585     return Associator<T, DefaultCandidate>::get(b.get());
0586   }
0587 
0588   static auto get(const immediate_executor_binder<T, Executor>& b,
0589       const DefaultCandidate& c) noexcept
0590     -> decltype(Associator<T, DefaultCandidate>::get(b.get(), c))
0591   {
0592     return Associator<T, DefaultCandidate>::get(b.get(), c);
0593   }
0594 };
0595 
0596 template <typename T, typename Executor, typename Executor1>
0597 struct associated_immediate_executor<
0598     immediate_executor_binder<T, Executor>,
0599     Executor1>
0600 {
0601   typedef Executor type;
0602 
0603   static auto get(const immediate_executor_binder<T, Executor>& b,
0604       const Executor1& = Executor1()) noexcept
0605     -> decltype(b.get_immediate_executor())
0606   {
0607     return b.get_immediate_executor();
0608   }
0609 };
0610 
0611 #endif // !defined(GENERATING_DOCUMENTATION)
0612 
0613 } // namespace asio
0614 } // namespace boost
0615 
0616 #include <boost/asio/detail/pop_options.hpp>
0617 
0618 #endif // BOOST_ASIO_BIND_IMMEDIATE_EXECUTOR_HPP