// // experimental/detail/channel_operation.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_ASIO_EXPERIMENTAL_DETAIL_CHANNEL_OPERATION_HPP #define BOOST_ASIO_EXPERIMENTAL_DETAIL_CHANNEL_OPERATION_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace asio { namespace experimental { namespace detail { // Base class for all channel operations. A function pointer is used instead of // virtual functions to avoid the associated overhead. class channel_operation BOOST_ASIO_INHERIT_TRACKED_HANDLER { public: template class handler_work_base; template class handler_work; void destroy() { func_(this, destroy_op, 0); } protected: enum action { destroy_op = 0, immediate_op = 1, post_op = 2, dispatch_op = 3, cancel_op = 4, close_op = 5 }; typedef void (*func_type)(channel_operation*, action, void*); channel_operation(func_type func) : next_(0), func_(func), cancellation_key_(0) { } // Prevents deletion through this type. ~channel_operation() { } friend class boost::asio::detail::op_queue_access; channel_operation* next_; func_type func_; public: // The operation key used for targeted cancellation. void* cancellation_key_; }; template class channel_operation::handler_work_base { public: typedef decay_t< prefer_result_t > executor_type; handler_work_base(int, const Executor& ex) : executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked)) { } const executor_type& get_executor() const noexcept { return executor_; } template void post(const IoExecutor& io_exec, Function& function, Handler&) { (boost::asio::detail::initiate_post_with_executor(io_exec))( static_cast(function)); } template void dispatch(Function& function, Handler& handler) { associated_allocator_t allocator = (get_associated_allocator)(handler); boost::asio::prefer(executor_, execution::allocator(allocator) ).execute(static_cast(function)); } private: executor_type executor_; }; template class channel_operation::handler_work_base::value >, enable_if_t< can_require::value > > { public: typedef decay_t< prefer_result_t > executor_type; handler_work_base(int, const Executor& ex) : executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked)) { } const executor_type& get_executor() const noexcept { return executor_; } template void post(const IoExecutor&, Function& function, Handler& handler) { associated_allocator_t allocator = (get_associated_allocator)(handler); boost::asio::prefer( boost::asio::require(executor_, execution::blocking.never), execution::allocator(allocator) ).execute(static_cast(function)); } template void dispatch(Function& function, Handler& handler) { associated_allocator_t allocator = (get_associated_allocator)(handler); boost::asio::prefer(executor_, execution::allocator(allocator) ).execute(static_cast(function)); } private: executor_type executor_; }; #if !defined(BOOST_ASIO_NO_TS_EXECUTORS) template class channel_operation::handler_work_base::value > > { public: typedef Executor executor_type; handler_work_base(int, const Executor& ex) : work_(ex) { } executor_type get_executor() const noexcept { return work_.get_executor(); } template void post(const IoExecutor&, Function& function, Handler& handler) { associated_allocator_t allocator = (get_associated_allocator)(handler); work_.get_executor().post( static_cast(function), allocator); } template void dispatch(Function& function, Handler& handler) { associated_allocator_t allocator = (get_associated_allocator)(handler); work_.get_executor().dispatch( static_cast(function), allocator); } private: executor_work_guard work_; }; #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS) template class channel_operation::handler_work : channel_operation::handler_work_base, channel_operation::handler_work_base< associated_executor_t, IoExecutor> { public: typedef channel_operation::handler_work_base base1_type; typedef channel_operation::handler_work_base< associated_executor_t, IoExecutor> base2_type; handler_work(Handler& handler, const IoExecutor& io_ex) noexcept : base1_type(0, io_ex), base2_type(0, (get_associated_executor)(handler, io_ex)) { } template void post(Function& function, Handler& handler) { base2_type::post(base1_type::get_executor(), function, handler); } template void dispatch(Function& function, Handler& handler) { base2_type::dispatch(function, handler); } template void immediate(Function& function, Handler& handler, ...) { typedef associated_immediate_executor_t immediate_ex_type; immediate_ex_type immediate_ex = (get_associated_immediate_executor)( handler, base1_type::get_executor()); (boost::asio::detail::initiate_dispatch_with_executor( immediate_ex))(static_cast(function)); } template void immediate(Function& function, Handler&, enable_if_t< is_same< typename associated_immediate_executor< conditional_t, typename base1_type::executor_type>:: asio_associated_immediate_executor_is_unspecialised, void >::value >*) { (boost::asio::detail::initiate_post_with_executor< typename base1_type::executor_type>( base1_type::get_executor()))( static_cast(function)); } }; template class channel_operation::handler_work< Handler, IoExecutor, enable_if_t< is_same< typename associated_executor::asio_associated_executor_is_unspecialised, void >::value > > : handler_work_base { public: typedef channel_operation::handler_work_base base1_type; handler_work(Handler&, const IoExecutor& io_ex) noexcept : base1_type(0, io_ex) { } template void post(Function& function, Handler& handler) { base1_type::post(base1_type::get_executor(), function, handler); } template void dispatch(Function& function, Handler& handler) { base1_type::dispatch(function, handler); } template void immediate(Function& function, Handler& handler, ...) { typedef associated_immediate_executor_t immediate_ex_type; immediate_ex_type immediate_ex = (get_associated_immediate_executor)( handler, base1_type::get_executor()); (boost::asio::detail::initiate_dispatch_with_executor( immediate_ex))(static_cast(function)); } template void immediate(Function& function, Handler& handler, enable_if_t< is_same< typename associated_immediate_executor< conditional_t, typename base1_type::executor_type>:: asio_associated_immediate_executor_is_unspecialised, void >::value >*) { base1_type::post(base1_type::get_executor(), function, handler); } }; } // namespace detail } // namespace experimental } // namespace asio } // namespace boost #include #endif // BOOST_ASIO_EXPERIMENTAL_DETAIL_CHANNEL_OPERATION_HPP