123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- //
- // 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 <boost/asio/detail/config.hpp>
- #include <boost/asio/associated_allocator.hpp>
- #include <boost/asio/associated_executor.hpp>
- #include <boost/asio/associated_immediate_executor.hpp>
- #include <boost/asio/detail/initiate_post.hpp>
- #include <boost/asio/detail/initiate_dispatch.hpp>
- #include <boost/asio/detail/op_queue.hpp>
- #include <boost/asio/detail/type_traits.hpp>
- #include <boost/asio/execution/executor.hpp>
- #include <boost/asio/execution/outstanding_work.hpp>
- #include <boost/asio/executor_work_guard.hpp>
- #include <boost/asio/prefer.hpp>
- #include <boost/asio/detail/push_options.hpp>
- 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 <typename Executor, typename = void, typename = void>
- class handler_work_base;
- template <typename Handler, typename IoExecutor, typename = void>
- 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 <typename Executor, typename, typename>
- class channel_operation::handler_work_base
- {
- public:
- typedef decay_t<
- prefer_result_t<Executor,
- execution::outstanding_work_t::tracked_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 <typename IoExecutor, typename Function, typename Handler>
- void post(const IoExecutor& io_exec, Function& function, Handler&)
- {
- (boost::asio::detail::initiate_post_with_executor<IoExecutor>(io_exec))(
- static_cast<Function&&>(function));
- }
- template <typename Function, typename Handler>
- void dispatch(Function& function, Handler& handler)
- {
- associated_allocator_t<Handler> allocator =
- (get_associated_allocator)(handler);
- boost::asio::prefer(executor_,
- execution::allocator(allocator)
- ).execute(static_cast<Function&&>(function));
- }
- private:
- executor_type executor_;
- };
- template <typename Executor>
- class channel_operation::handler_work_base<Executor,
- enable_if_t<
- execution::is_executor<Executor>::value
- >,
- enable_if_t<
- can_require<Executor, execution::blocking_t::never_t>::value
- >
- >
- {
- public:
- typedef decay_t<
- prefer_result_t<Executor,
- execution::outstanding_work_t::tracked_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 <typename IoExecutor, typename Function, typename Handler>
- void post(const IoExecutor&, Function& function, Handler& handler)
- {
- associated_allocator_t<Handler> allocator =
- (get_associated_allocator)(handler);
- boost::asio::prefer(
- boost::asio::require(executor_, execution::blocking.never),
- execution::allocator(allocator)
- ).execute(static_cast<Function&&>(function));
- }
- template <typename Function, typename Handler>
- void dispatch(Function& function, Handler& handler)
- {
- associated_allocator_t<Handler> allocator =
- (get_associated_allocator)(handler);
- boost::asio::prefer(executor_,
- execution::allocator(allocator)
- ).execute(static_cast<Function&&>(function));
- }
- private:
- executor_type executor_;
- };
- #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
- template <typename Executor>
- class channel_operation::handler_work_base<Executor,
- enable_if_t<
- !execution::is_executor<Executor>::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 <typename IoExecutor, typename Function, typename Handler>
- void post(const IoExecutor&, Function& function, Handler& handler)
- {
- associated_allocator_t<Handler> allocator =
- (get_associated_allocator)(handler);
- work_.get_executor().post(
- static_cast<Function&&>(function), allocator);
- }
- template <typename Function, typename Handler>
- void dispatch(Function& function, Handler& handler)
- {
- associated_allocator_t<Handler> allocator =
- (get_associated_allocator)(handler);
- work_.get_executor().dispatch(
- static_cast<Function&&>(function), allocator);
- }
- private:
- executor_work_guard<Executor> work_;
- };
- #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
- template <typename Handler, typename IoExecutor, typename>
- class channel_operation::handler_work :
- channel_operation::handler_work_base<IoExecutor>,
- channel_operation::handler_work_base<
- associated_executor_t<Handler, IoExecutor>, IoExecutor>
- {
- public:
- typedef channel_operation::handler_work_base<IoExecutor> base1_type;
- typedef channel_operation::handler_work_base<
- associated_executor_t<Handler, IoExecutor>, 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 <typename Function>
- void post(Function& function, Handler& handler)
- {
- base2_type::post(base1_type::get_executor(), function, handler);
- }
- template <typename Function>
- void dispatch(Function& function, Handler& handler)
- {
- base2_type::dispatch(function, handler);
- }
- template <typename Function>
- void immediate(Function& function, Handler& handler, ...)
- {
- typedef associated_immediate_executor_t<Handler,
- typename base1_type::executor_type> 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_type>(
- immediate_ex))(static_cast<Function&&>(function));
- }
- template <typename Function>
- void immediate(Function& function, Handler&,
- enable_if_t<
- is_same<
- typename associated_immediate_executor<
- conditional_t<false, Function, Handler>,
- 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&&>(function));
- }
- };
- template <typename Handler, typename IoExecutor>
- class channel_operation::handler_work<
- Handler, IoExecutor,
- enable_if_t<
- is_same<
- typename associated_executor<Handler,
- IoExecutor>::asio_associated_executor_is_unspecialised,
- void
- >::value
- >
- > : handler_work_base<IoExecutor>
- {
- public:
- typedef channel_operation::handler_work_base<IoExecutor> base1_type;
- handler_work(Handler&, const IoExecutor& io_ex) noexcept
- : base1_type(0, io_ex)
- {
- }
- template <typename Function>
- void post(Function& function, Handler& handler)
- {
- base1_type::post(base1_type::get_executor(), function, handler);
- }
- template <typename Function>
- void dispatch(Function& function, Handler& handler)
- {
- base1_type::dispatch(function, handler);
- }
- template <typename Function>
- void immediate(Function& function, Handler& handler, ...)
- {
- typedef associated_immediate_executor_t<Handler,
- typename base1_type::executor_type> 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_type>(
- immediate_ex))(static_cast<Function&&>(function));
- }
- template <typename Function>
- void immediate(Function& function, Handler& handler,
- enable_if_t<
- is_same<
- typename associated_immediate_executor<
- conditional_t<false, Function, Handler>,
- 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 <boost/asio/detail/pop_options.hpp>
- #endif // BOOST_ASIO_EXPERIMENTAL_DETAIL_CHANNEL_OPERATION_HPP
|