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 24 namespace asio { 25 namespace detail { 26 27 template <typename Handler> 28 class reactive_null_buffers_op : public reactor_op 29 { 30 public: 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 76 private: 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