Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:33:42

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