2 // experimental/detail/channel_send_op.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 #ifndef BOOST_ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_OP_HPP
12 #define BOOST_ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_OP_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
19 #include <boost/asio/detail/bind_handler.hpp>
20 #include <boost/asio/detail/handler_alloc_helpers.hpp>
21 #include <boost/asio/error.hpp>
22 #include <boost/asio/experimental/channel_error.hpp>
23 #include <boost/asio/experimental/detail/channel_operation.hpp>
24 #include <boost/asio/experimental/detail/channel_payload.hpp>
26 #include <boost/asio/detail/push_options.hpp>
30 namespace experimental {
33 template <typename Payload>
34 class channel_send : public channel_operation
39 return BOOST_ASIO_MOVE_CAST(Payload)(payload_);
44 func_(this, complete_op, 0);
49 func_(this, cancel_op, 0);
54 func_(this, close_op, 0);
58 channel_send(func_type func, BOOST_ASIO_MOVE_ARG(Payload) payload)
59 : channel_operation(func),
60 payload_(BOOST_ASIO_MOVE_CAST(Payload)(payload))
68 template <typename Payload, typename Handler, typename IoExecutor>
69 class channel_send_op : public channel_send<Payload>
72 BOOST_ASIO_DEFINE_HANDLER_PTR(channel_send_op);
74 channel_send_op(BOOST_ASIO_MOVE_ARG(Payload) payload,
75 Handler& handler, const IoExecutor& io_ex)
76 : channel_send<Payload>(&channel_send_op::do_action,
77 BOOST_ASIO_MOVE_CAST(Payload)(payload)),
78 handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
79 work_(handler_, io_ex)
83 static void do_action(channel_operation* base,
84 channel_operation::action a, void*)
86 // Take ownership of the operation object.
87 channel_send_op* o(static_cast<channel_send_op*>(base));
88 ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
90 BOOST_ASIO_HANDLER_COMPLETION((*o));
92 // Take ownership of the operation's outstanding work.
93 channel_operation::handler_work<Handler, IoExecutor> w(
94 BOOST_ASIO_MOVE_CAST2(channel_operation::handler_work<
95 Handler, IoExecutor>)(o->work_));
97 boost::system::error_code ec;
100 case channel_operation::cancel_op:
101 ec = error::channel_cancelled;
103 case channel_operation::close_op:
104 ec = error::channel_closed;
110 // Make a copy of the handler so that the memory can be deallocated before
111 // the handler is posted. Even if we're not about to post the handler, a
112 // sub-object of the handler may be the true owner of the memory associated
113 // with the handler. Consequently, a local copy of the handler is required
114 // to ensure that any owning sub-object remains valid until after we have
115 // deallocated the memory here.
116 boost::asio::detail::binder1<Handler, boost::system::error_code>
117 handler(o->handler_, ec);
118 p.h = boost::asio::detail::addressof(handler.handler_);
121 // Post the completion if required.
122 if (a != channel_operation::destroy_op)
124 BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
125 w.complete(handler, handler.handler_);
126 BOOST_ASIO_HANDLER_INVOCATION_END;
132 channel_operation::handler_work<Handler, IoExecutor> work_;
135 } // namespace detail
136 } // namespace experimental
140 #include <boost/asio/detail/pop_options.hpp>
142 #endif // BOOST_ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_OP_HPP