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