1//
2// detail/reactive_null_buffers_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_NULL_BUFFERS_OP_HPP
12#define ASIO_DETAIL_REACTIVE_NULL_BUFFERS_OP_HPP
13
14
15#include "asio/detail/config.hpp"
16#include "asio/detail/addressof.hpp"
17#include "asio/detail/fenced_block.hpp"
18#include "asio/detail/handler_alloc_helpers.hpp"
19#include "asio/detail/handler_invoke_helpers.hpp"
20#include "asio/detail/reactor_op.hpp"
21
22#include "asio/detail/push_options.hpp"
23
24namespace asio {
25namespace detail {
26
27template <typename Handler>
28class reactive_null_buffers_op : public reactor_op
29{
30public:
31  ASIO_DEFINE_HANDLER_PTR(reactive_null_buffers_op);
32
33  reactive_null_buffers_op(Handler& handler)
34    : reactor_op(&reactive_null_buffers_op::do_perform,
35        &reactive_null_buffers_op::do_complete),
36      handler_(ASIO_MOVE_CAST(Handler)(handler))
37  {
38  }
39
40  static bool do_perform(reactor_op*)
41  {
42    return true;
43  }
44
45  static void do_complete(io_service_impl* owner, operation* base,
46      const asio::error_code& /*ec*/,
47      std::size_t /*bytes_transferred*/)
48  {
49    // Take ownership of the handler object.
50    reactive_null_buffers_op* o(static_cast<reactive_null_buffers_op*>(base));
51    ptr p = { asio::detail::addressof(o->handler_), o, o };
52
53    ASIO_HANDLER_COMPLETION((o));
54
55    // Make a copy of the handler so that the memory can be deallocated before
56    // the upcall is made. Even if we're not about to make an upcall, a
57    // sub-object of the handler may be the true owner of the memory associated
58    // with the handler. Consequently, a local copy of the handler is required
59    // to ensure that any owning sub-object remains valid until after we have
60    // deallocated the memory here.
61    detail::binder2<Handler, asio::error_code, std::size_t>
62      handler(o->handler_, o->ec_, o->bytes_transferred_);
63    p.h = asio::detail::addressof(handler.handler_);
64    p.reset();
65
66    // Make the upcall if required.
67    if (owner)
68    {
69      fenced_block b(fenced_block::half);
70      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
71      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
72      ASIO_HANDLER_INVOCATION_END;
73    }
74  }
75
76private:
77  Handler handler_;
78};
79
80} // namespace detail
81} // namespace asio
82
83#include "asio/detail/pop_options.hpp"
84
85#endif // ASIO_DETAIL_REACTIVE_NULL_BUFFERS_OP_HPP
86