Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:50

0001 //
0002 // experimental/detail/channel_operation.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_EXPERIMENTAL_DETAIL_CHANNEL_OPERATION_HPP
0012 #define BOOST_ASIO_EXPERIMENTAL_DETAIL_CHANNEL_OPERATION_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_allocator.hpp>
0020 #include <boost/asio/associated_executor.hpp>
0021 #include <boost/asio/associated_immediate_executor.hpp>
0022 #include <boost/asio/detail/initiate_post.hpp>
0023 #include <boost/asio/detail/initiate_dispatch.hpp>
0024 #include <boost/asio/detail/op_queue.hpp>
0025 #include <boost/asio/detail/type_traits.hpp>
0026 #include <boost/asio/execution/executor.hpp>
0027 #include <boost/asio/execution/outstanding_work.hpp>
0028 #include <boost/asio/executor_work_guard.hpp>
0029 #include <boost/asio/prefer.hpp>
0030 
0031 #include <boost/asio/detail/push_options.hpp>
0032 
0033 namespace boost {
0034 namespace asio {
0035 namespace experimental {
0036 namespace detail {
0037 
0038 // Base class for all channel operations. A function pointer is used instead of
0039 // virtual functions to avoid the associated overhead.
0040 class channel_operation BOOST_ASIO_INHERIT_TRACKED_HANDLER
0041 {
0042 public:
0043   template <typename Executor, typename = void, typename = void>
0044   class handler_work_base;
0045 
0046   template <typename Handler, typename IoExecutor, typename = void>
0047   class handler_work;
0048 
0049   void destroy()
0050   {
0051     func_(this, destroy_op, 0);
0052   }
0053 
0054 protected:
0055   enum action
0056   {
0057     destroy_op = 0,
0058     immediate_op = 1,
0059     post_op = 2,
0060     dispatch_op = 3,
0061     cancel_op = 4,
0062     close_op = 5
0063   };
0064 
0065   typedef void (*func_type)(channel_operation*, action, void*);
0066 
0067   channel_operation(func_type func)
0068     : next_(0),
0069       func_(func),
0070       cancellation_key_(0)
0071   {
0072   }
0073 
0074   // Prevents deletion through this type.
0075   ~channel_operation()
0076   {
0077   }
0078 
0079   friend class boost::asio::detail::op_queue_access;
0080   channel_operation* next_;
0081   func_type func_;
0082 
0083 public:
0084   // The operation key used for targeted cancellation.
0085   void* cancellation_key_;
0086 };
0087 
0088 template <typename Executor, typename, typename>
0089 class channel_operation::handler_work_base
0090 {
0091 public:
0092   typedef decay_t<
0093       prefer_result_t<Executor,
0094         execution::outstanding_work_t::tracked_t
0095       >
0096     > executor_type;
0097 
0098   handler_work_base(int, const Executor& ex)
0099     : executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
0100   {
0101   }
0102 
0103   const executor_type& get_executor() const noexcept
0104   {
0105     return executor_;
0106   }
0107 
0108   template <typename IoExecutor, typename Function, typename Handler>
0109   void post(const IoExecutor& io_exec, Function& function, Handler&)
0110   {
0111     (boost::asio::detail::initiate_post_with_executor<IoExecutor>(io_exec))(
0112         static_cast<Function&&>(function));
0113   }
0114 
0115   template <typename Function, typename Handler>
0116   void dispatch(Function& function, Handler& handler)
0117   {
0118     associated_allocator_t<Handler> allocator =
0119       (get_associated_allocator)(handler);
0120 
0121     boost::asio::prefer(executor_,
0122         execution::allocator(allocator)
0123       ).execute(static_cast<Function&&>(function));
0124   }
0125 
0126 private:
0127   executor_type executor_;
0128 };
0129 
0130 template <typename Executor>
0131 class channel_operation::handler_work_base<Executor,
0132     enable_if_t<
0133       execution::is_executor<Executor>::value
0134     >,
0135     enable_if_t<
0136       can_require<Executor, execution::blocking_t::never_t>::value
0137     >
0138   >
0139 {
0140 public:
0141   typedef decay_t<
0142       prefer_result_t<Executor,
0143         execution::outstanding_work_t::tracked_t
0144       >
0145     > executor_type;
0146 
0147   handler_work_base(int, const Executor& ex)
0148     : executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
0149   {
0150   }
0151 
0152   const executor_type& get_executor() const noexcept
0153   {
0154     return executor_;
0155   }
0156 
0157   template <typename IoExecutor, typename Function, typename Handler>
0158   void post(const IoExecutor&, Function& function, Handler& handler)
0159   {
0160     associated_allocator_t<Handler> allocator =
0161       (get_associated_allocator)(handler);
0162 
0163     boost::asio::prefer(
0164         boost::asio::require(executor_, execution::blocking.never),
0165         execution::allocator(allocator)
0166       ).execute(static_cast<Function&&>(function));
0167   }
0168 
0169   template <typename Function, typename Handler>
0170   void dispatch(Function& function, Handler& handler)
0171   {
0172     associated_allocator_t<Handler> allocator =
0173       (get_associated_allocator)(handler);
0174 
0175     boost::asio::prefer(executor_,
0176         execution::allocator(allocator)
0177       ).execute(static_cast<Function&&>(function));
0178   }
0179 
0180 private:
0181   executor_type executor_;
0182 };
0183 
0184 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0185 
0186 template <typename Executor>
0187 class channel_operation::handler_work_base<Executor,
0188     enable_if_t<
0189       !execution::is_executor<Executor>::value
0190     >
0191   >
0192 {
0193 public:
0194   typedef Executor executor_type;
0195 
0196   handler_work_base(int, const Executor& ex)
0197     : work_(ex)
0198   {
0199   }
0200 
0201   executor_type get_executor() const noexcept
0202   {
0203     return work_.get_executor();
0204   }
0205 
0206   template <typename IoExecutor, typename Function, typename Handler>
0207   void post(const IoExecutor&, Function& function, Handler& handler)
0208   {
0209     associated_allocator_t<Handler> allocator =
0210       (get_associated_allocator)(handler);
0211 
0212     work_.get_executor().post(
0213         static_cast<Function&&>(function), allocator);
0214   }
0215 
0216   template <typename Function, typename Handler>
0217   void dispatch(Function& function, Handler& handler)
0218   {
0219     associated_allocator_t<Handler> allocator =
0220       (get_associated_allocator)(handler);
0221 
0222     work_.get_executor().dispatch(
0223         static_cast<Function&&>(function), allocator);
0224   }
0225 
0226 private:
0227   executor_work_guard<Executor> work_;
0228 };
0229 
0230 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0231 
0232 template <typename Handler, typename IoExecutor, typename>
0233 class channel_operation::handler_work :
0234   channel_operation::handler_work_base<IoExecutor>,
0235   channel_operation::handler_work_base<
0236       associated_executor_t<Handler, IoExecutor>, IoExecutor>
0237 {
0238 public:
0239   typedef channel_operation::handler_work_base<IoExecutor> base1_type;
0240 
0241   typedef channel_operation::handler_work_base<
0242       associated_executor_t<Handler, IoExecutor>, IoExecutor>
0243     base2_type;
0244 
0245   handler_work(Handler& handler, const IoExecutor& io_ex) noexcept
0246     : base1_type(0, io_ex),
0247       base2_type(0, (get_associated_executor)(handler, io_ex))
0248   {
0249   }
0250 
0251   template <typename Function>
0252   void post(Function& function, Handler& handler)
0253   {
0254     base2_type::post(base1_type::get_executor(), function, handler);
0255   }
0256 
0257   template <typename Function>
0258   void dispatch(Function& function, Handler& handler)
0259   {
0260     base2_type::dispatch(function, handler);
0261   }
0262 
0263   template <typename Function>
0264   void immediate(Function& function, Handler& handler, ...)
0265   {
0266     typedef associated_immediate_executor_t<Handler,
0267       typename base1_type::executor_type> immediate_ex_type;
0268 
0269     immediate_ex_type immediate_ex = (get_associated_immediate_executor)(
0270         handler, base1_type::get_executor());
0271 
0272     (boost::asio::detail::initiate_dispatch_with_executor<immediate_ex_type>(
0273           immediate_ex))(static_cast<Function&&>(function));
0274   }
0275 
0276   template <typename Function>
0277   void immediate(Function& function, Handler&,
0278       enable_if_t<
0279         is_same<
0280           typename associated_immediate_executor<
0281             conditional_t<false, Function, Handler>,
0282             typename base1_type::executor_type>::
0283               asio_associated_immediate_executor_is_unspecialised,
0284           void
0285         >::value
0286       >*)
0287   {
0288     (boost::asio::detail::initiate_post_with_executor<
0289         typename base1_type::executor_type>(
0290           base1_type::get_executor()))(
0291         static_cast<Function&&>(function));
0292   }
0293 };
0294 
0295 template <typename Handler, typename IoExecutor>
0296 class channel_operation::handler_work<
0297     Handler, IoExecutor,
0298     enable_if_t<
0299       is_same<
0300         typename associated_executor<Handler,
0301           IoExecutor>::asio_associated_executor_is_unspecialised,
0302         void
0303       >::value
0304     >
0305   > : handler_work_base<IoExecutor>
0306 {
0307 public:
0308   typedef channel_operation::handler_work_base<IoExecutor> base1_type;
0309 
0310   handler_work(Handler&, const IoExecutor& io_ex) noexcept
0311     : base1_type(0, io_ex)
0312   {
0313   }
0314 
0315   template <typename Function>
0316   void post(Function& function, Handler& handler)
0317   {
0318     base1_type::post(base1_type::get_executor(), function, handler);
0319   }
0320 
0321   template <typename Function>
0322   void dispatch(Function& function, Handler& handler)
0323   {
0324     base1_type::dispatch(function, handler);
0325   }
0326 
0327   template <typename Function>
0328   void immediate(Function& function, Handler& handler, ...)
0329   {
0330     typedef associated_immediate_executor_t<Handler,
0331       typename base1_type::executor_type> immediate_ex_type;
0332 
0333     immediate_ex_type immediate_ex = (get_associated_immediate_executor)(
0334         handler, base1_type::get_executor());
0335 
0336     (boost::asio::detail::initiate_dispatch_with_executor<immediate_ex_type>(
0337           immediate_ex))(static_cast<Function&&>(function));
0338   }
0339 
0340   template <typename Function>
0341   void immediate(Function& function, Handler& handler,
0342       enable_if_t<
0343         is_same<
0344           typename associated_immediate_executor<
0345             conditional_t<false, Function, Handler>,
0346             typename base1_type::executor_type>::
0347               asio_associated_immediate_executor_is_unspecialised,
0348           void
0349         >::value
0350       >*)
0351   {
0352     base1_type::post(base1_type::get_executor(), function, handler);
0353   }
0354 };
0355 
0356 } // namespace detail
0357 } // namespace experimental
0358 } // namespace asio
0359 } // namespace boost
0360 
0361 #include <boost/asio/detail/pop_options.hpp>
0362 
0363 #endif // BOOST_ASIO_EXPERIMENTAL_DETAIL_CHANNEL_OPERATION_HPP