Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-07 09:33:54

0001 //
0002 // bind_immediate_executor.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_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) &&
0362   {
0363     return static_cast<T&&>(target_)(static_cast<Args&&>(args)...);
0364   }
0365 
0366   /// Forwarding function call operator.
0367   template <typename... Args>
0368   result_of_t<T(Args...)> operator()(Args&&... args) const&
0369   {
0370     return target_(static_cast<Args&&>(args)...);
0371   }
0372 
0373 private:
0374   Executor executor_;
0375   T target_;
0376 };
0377 
0378 /// A function object type that adapts a @ref completion_token to specify that
0379 /// the completion handler should have the supplied executor as its associated
0380 /// immediate executor.
0381 /**
0382  * May also be used directly as a completion token, in which case it adapts the
0383  * asynchronous operation's default completion token (or boost::asio::deferred
0384  * if no default is available).
0385  */
0386 template <typename Executor>
0387 struct partial_immediate_executor_binder
0388 {
0389   /// Constructor that specifies associated executor.
0390   explicit partial_immediate_executor_binder(const Executor& ex)
0391     : executor_(ex)
0392   {
0393   }
0394 
0395   /// Adapt a @ref completion_token to specify that the completion handler
0396   /// should have the executor as its associated immediate executor.
0397   template <typename CompletionToken>
0398   BOOST_ASIO_NODISCARD inline
0399   constexpr immediate_executor_binder<decay_t<CompletionToken>, Executor>
0400   operator()(CompletionToken&& completion_token) const
0401   {
0402     return immediate_executor_binder<decay_t<CompletionToken>, Executor>(
0403         static_cast<CompletionToken&&>(completion_token), executor_);
0404   }
0405 
0406 //private:
0407   Executor executor_;
0408 };
0409 
0410 /// Create a partial completion token that associates an executor.
0411 template <typename Executor>
0412 BOOST_ASIO_NODISCARD inline partial_immediate_executor_binder<Executor>
0413 bind_immediate_executor(const Executor& ex)
0414 {
0415   return partial_immediate_executor_binder<Executor>(ex);
0416 }
0417 
0418 /// Associate an object of type @c T with a immediate executor of type
0419 /// @c Executor.
0420 template <typename Executor, typename T>
0421 BOOST_ASIO_NODISCARD inline immediate_executor_binder<decay_t<T>, Executor>
0422 bind_immediate_executor(const Executor& e, T&& t)
0423 {
0424   return immediate_executor_binder<
0425     decay_t<T>, Executor>(
0426       e, static_cast<T&&>(t));
0427 }
0428 
0429 #if !defined(GENERATING_DOCUMENTATION)
0430 
0431 namespace detail {
0432 
0433 template <typename TargetAsyncResult, typename Executor, typename = void>
0434 class immediate_executor_binder_completion_handler_async_result
0435 {
0436 public:
0437   template <typename T>
0438   explicit immediate_executor_binder_completion_handler_async_result(T&)
0439   {
0440   }
0441 };
0442 
0443 template <typename TargetAsyncResult, typename Executor>
0444 class immediate_executor_binder_completion_handler_async_result<
0445   TargetAsyncResult, Executor,
0446   void_t<
0447     typename TargetAsyncResult::completion_handler_type
0448   >>
0449 {
0450 private:
0451   TargetAsyncResult target_;
0452 
0453 public:
0454   typedef immediate_executor_binder<
0455     typename TargetAsyncResult::completion_handler_type, Executor>
0456       completion_handler_type;
0457 
0458   explicit immediate_executor_binder_completion_handler_async_result(
0459       typename TargetAsyncResult::completion_handler_type& handler)
0460     : target_(handler)
0461   {
0462   }
0463 
0464   auto get() -> decltype(target_.get())
0465   {
0466     return target_.get();
0467   }
0468 };
0469 
0470 template <typename TargetAsyncResult, typename = void>
0471 struct immediate_executor_binder_async_result_return_type
0472 {
0473 };
0474 
0475 template <typename TargetAsyncResult>
0476 struct immediate_executor_binder_async_result_return_type<
0477   TargetAsyncResult,
0478   void_t<
0479     typename TargetAsyncResult::return_type
0480   >>
0481 {
0482   typedef typename TargetAsyncResult::return_type return_type;
0483 };
0484 
0485 } // namespace detail
0486 
0487 template <typename T, typename Executor, typename Signature>
0488 class async_result<immediate_executor_binder<T, Executor>, Signature> :
0489   public detail::immediate_executor_binder_completion_handler_async_result<
0490     async_result<T, Signature>, Executor>,
0491   public detail::immediate_executor_binder_async_result_return_type<
0492     async_result<T, Signature>>
0493 {
0494 public:
0495   explicit async_result(immediate_executor_binder<T, Executor>& b)
0496     : detail::immediate_executor_binder_completion_handler_async_result<
0497         async_result<T, Signature>, Executor>(b.get())
0498   {
0499   }
0500 
0501   template <typename Initiation>
0502   struct init_wrapper : detail::initiation_base<Initiation>
0503   {
0504     using detail::initiation_base<Initiation>::initiation_base;
0505 
0506     template <typename Handler, typename... Args>
0507     void operator()(Handler&& handler, const Executor& e, Args&&... args) &&
0508     {
0509       static_cast<Initiation&&>(*this)(
0510           immediate_executor_binder<
0511             decay_t<Handler>, Executor>(
0512               e, static_cast<Handler&&>(handler)),
0513           static_cast<Args&&>(args)...);
0514     }
0515 
0516     template <typename Handler, typename... Args>
0517     void operator()(Handler&& handler,
0518         const Executor& e, Args&&... args) const &
0519     {
0520       static_cast<const Initiation&>(*this)(
0521           immediate_executor_binder<
0522             decay_t<Handler>, Executor>(
0523               e, static_cast<Handler&&>(handler)),
0524           static_cast<Args&&>(args)...);
0525     }
0526   };
0527 
0528   template <typename Initiation, typename RawCompletionToken, typename... Args>
0529   static auto initiate(Initiation&& initiation,
0530       RawCompletionToken&& token, Args&&... args)
0531     -> decltype(
0532       async_initiate<
0533         conditional_t<
0534           is_const<remove_reference_t<RawCompletionToken>>::value, const T, T>,
0535         Signature>(
0536           declval<init_wrapper<decay_t<Initiation>>>(),
0537           token.get(), token.get_immediate_executor(),
0538           static_cast<Args&&>(args)...))
0539   {
0540     return async_initiate<
0541       conditional_t<
0542         is_const<remove_reference_t<RawCompletionToken>>::value, const T, T>,
0543       Signature>(
0544         init_wrapper<decay_t<Initiation>>(
0545           static_cast<Initiation&&>(initiation)),
0546         token.get(), token.get_immediate_executor(),
0547         static_cast<Args&&>(args)...);
0548   }
0549 
0550 private:
0551   async_result(const async_result&) = delete;
0552   async_result& operator=(const async_result&) = delete;
0553 
0554   async_result<T, Signature> target_;
0555 };
0556 
0557 template <typename Executor, typename... Signatures>
0558 struct async_result<partial_immediate_executor_binder<Executor>, Signatures...>
0559 {
0560   template <typename Initiation, typename RawCompletionToken, typename... Args>
0561   static auto initiate(Initiation&& initiation,
0562       RawCompletionToken&& token, Args&&... args)
0563     -> decltype(
0564       async_initiate<Signatures...>(
0565         static_cast<Initiation&&>(initiation),
0566         immediate_executor_binder<
0567           default_completion_token_t<associated_executor_t<Initiation>>,
0568           Executor>(token.executor_,
0569             default_completion_token_t<associated_executor_t<Initiation>>{}),
0570         static_cast<Args&&>(args)...))
0571   {
0572     return async_initiate<Signatures...>(
0573         static_cast<Initiation&&>(initiation),
0574         immediate_executor_binder<
0575           default_completion_token_t<associated_executor_t<Initiation>>,
0576           Executor>(token.executor_,
0577             default_completion_token_t<associated_executor_t<Initiation>>{}),
0578         static_cast<Args&&>(args)...);
0579   }
0580 };
0581 
0582 template <template <typename, typename> class Associator,
0583     typename T, typename Executor, typename DefaultCandidate>
0584 struct associator<Associator,
0585     immediate_executor_binder<T, Executor>,
0586     DefaultCandidate>
0587   : Associator<T, DefaultCandidate>
0588 {
0589   static typename Associator<T, DefaultCandidate>::type get(
0590       const immediate_executor_binder<T, Executor>& b) noexcept
0591   {
0592     return Associator<T, DefaultCandidate>::get(b.get());
0593   }
0594 
0595   static auto get(const immediate_executor_binder<T, Executor>& b,
0596       const DefaultCandidate& c) noexcept
0597     -> decltype(Associator<T, DefaultCandidate>::get(b.get(), c))
0598   {
0599     return Associator<T, DefaultCandidate>::get(b.get(), c);
0600   }
0601 };
0602 
0603 template <typename T, typename Executor, typename Executor1>
0604 struct associated_immediate_executor<
0605     immediate_executor_binder<T, Executor>,
0606     Executor1>
0607 {
0608   typedef Executor type;
0609 
0610   static auto get(const immediate_executor_binder<T, Executor>& b,
0611       const Executor1& = Executor1()) noexcept
0612     -> decltype(b.get_immediate_executor())
0613   {
0614     return b.get_immediate_executor();
0615   }
0616 };
0617 
0618 #endif // !defined(GENERATING_DOCUMENTATION)
0619 
0620 } // namespace asio
0621 } // namespace boost
0622 
0623 #include <boost/asio/detail/pop_options.hpp>
0624 
0625 #endif // BOOST_ASIO_BIND_IMMEDIATE_EXECUTOR_HPP