File indexing completed on 2025-01-18 09:28:50
0001
0002
0003
0004
0005
0006
0007
0008
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
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
0039
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
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
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
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 }
0357 }
0358 }
0359 }
0360
0361 #include <boost/asio/detail/pop_options.hpp>
0362
0363 #endif