1//
2// detail/reactive_socket_recvmsg_op.hpp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6//
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)
9//
10
11#ifndef ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_HPP
12#define ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_HPP
13
14
15#include "asio/detail/config.hpp"
16#include "asio/detail/addressof.hpp"
17#include "asio/detail/bind_handler.hpp"
18#include "asio/detail/buffer_sequence_adapter.hpp"
19#include "asio/detail/fenced_block.hpp"
20#include "asio/detail/reactor_op.hpp"
21#include "asio/detail/socket_ops.hpp"
22#include "asio/socket_base.hpp"
23
24#include "asio/detail/push_options.hpp"
25
26namespace asio {
27namespace detail {
28
29template <typename MutableBufferSequence>
30class reactive_socket_recvmsg_op_base : public reactor_op
31{
32public:
33  reactive_socket_recvmsg_op_base(socket_type socket,
34      const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
35      socket_base::message_flags& out_flags, func_type complete_func)
36    : reactor_op(&reactive_socket_recvmsg_op_base::do_perform, complete_func),
37      socket_(socket),
38      buffers_(buffers),
39      in_flags_(in_flags),
40      out_flags_(out_flags)
41  {
42  }
43
44  static bool do_perform(reactor_op* base)
45  {
46    reactive_socket_recvmsg_op_base* o(
47        static_cast<reactive_socket_recvmsg_op_base*>(base));
48
49    buffer_sequence_adapter<asio::mutable_buffer,
50        MutableBufferSequence> bufs(o->buffers_);
51
52    return socket_ops::non_blocking_recvmsg(o->socket_,
53        bufs.buffers(), bufs.count(),
54        o->in_flags_, o->out_flags_,
55        o->ec_, o->bytes_transferred_);
56  }
57
58private:
59  socket_type socket_;
60  MutableBufferSequence buffers_;
61  socket_base::message_flags in_flags_;
62  socket_base::message_flags& out_flags_;
63};
64
65template <typename MutableBufferSequence, typename Handler>
66class reactive_socket_recvmsg_op :
67  public reactive_socket_recvmsg_op_base<MutableBufferSequence>
68{
69public:
70  ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op);
71
72  reactive_socket_recvmsg_op(socket_type socket,
73      const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
74      socket_base::message_flags& out_flags, Handler& handler)
75    : reactive_socket_recvmsg_op_base<MutableBufferSequence>(socket, buffers,
76        in_flags, out_flags, &reactive_socket_recvmsg_op::do_complete),
77      handler_(ASIO_MOVE_CAST(Handler)(handler))
78  {
79  }
80
81  static void do_complete(io_service_impl* owner, operation* base,
82      const asio::error_code& /*ec*/,
83      std::size_t /*bytes_transferred*/)
84  {
85    // Take ownership of the handler object.
86    reactive_socket_recvmsg_op* o(
87        static_cast<reactive_socket_recvmsg_op*>(base));
88    ptr p = { asio::detail::addressof(o->handler_), o, o };
89
90    ASIO_HANDLER_COMPLETION((o));
91
92    // Make a copy of the handler so that the memory can be deallocated before
93    // the upcall is made. Even if we're not about to make an upcall, a
94    // sub-object of the handler may be the true owner of the memory associated
95    // with the handler. Consequently, a local copy of the handler is required
96    // to ensure that any owning sub-object remains valid until after we have
97    // deallocated the memory here.
98    detail::binder2<Handler, asio::error_code, std::size_t>
99      handler(o->handler_, o->ec_, o->bytes_transferred_);
100    p.h = asio::detail::addressof(handler.handler_);
101    p.reset();
102
103    // Make the upcall if required.
104    if (owner)
105    {
106      fenced_block b(fenced_block::half);
107      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
108      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
109      ASIO_HANDLER_INVOCATION_END;
110    }
111  }
112
113private:
114  Handler handler_;
115};
116
117} // namespace detail
118} // namespace asio
119
120#include "asio/detail/pop_options.hpp"
121
122#endif // ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_HPP
123