1 // 2 // detail/reactive_socket_connect_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_CONNECT_OP_HPP 12 #define ASIO_DETAIL_REACTIVE_SOCKET_CONNECT_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 23 #include "asio/detail/push_options.hpp" 24 25 namespace asio { 26 namespace detail { 27 28 class reactive_socket_connect_op_base : public reactor_op 29 { 30 public: reactive_socket_connect_op_base(socket_type socket,func_type complete_func)31 reactive_socket_connect_op_base(socket_type socket, func_type complete_func) 32 : reactor_op(&reactive_socket_connect_op_base::do_perform, complete_func), 33 socket_(socket) 34 { 35 } 36 do_perform(reactor_op * base)37 static bool do_perform(reactor_op* base) 38 { 39 reactive_socket_connect_op_base* o( 40 static_cast<reactive_socket_connect_op_base*>(base)); 41 42 return socket_ops::non_blocking_connect(o->socket_, o->ec_); 43 } 44 45 private: 46 socket_type socket_; 47 }; 48 49 template <typename Handler> 50 class reactive_socket_connect_op : public reactive_socket_connect_op_base 51 { 52 public: 53 ASIO_DEFINE_HANDLER_PTR(reactive_socket_connect_op); 54 reactive_socket_connect_op(socket_type socket,Handler & handler)55 reactive_socket_connect_op(socket_type socket, Handler& handler) 56 : reactive_socket_connect_op_base(socket, 57 &reactive_socket_connect_op::do_complete), 58 handler_(ASIO_MOVE_CAST(Handler)(handler)) 59 { 60 } 61 do_complete(io_service_impl * owner,operation * base,const asio::error_code &,std::size_t)62 static void do_complete(io_service_impl* owner, operation* base, 63 const asio::error_code& /*ec*/, 64 std::size_t /*bytes_transferred*/) 65 { 66 // Take ownership of the handler object. 67 reactive_socket_connect_op* o 68 (static_cast<reactive_socket_connect_op*>(base)); 69 ptr p = { asio::detail::addressof(o->handler_), o, o }; 70 71 ASIO_HANDLER_COMPLETION((o)); 72 73 // Make a copy of the handler so that the memory can be deallocated before 74 // the upcall is made. Even if we're not about to make an upcall, a 75 // sub-object of the handler may be the true owner of the memory associated 76 // with the handler. Consequently, a local copy of the handler is required 77 // to ensure that any owning sub-object remains valid until after we have 78 // deallocated the memory here. 79 detail::binder1<Handler, asio::error_code> 80 handler(o->handler_, o->ec_); 81 p.h = asio::detail::addressof(handler.handler_); 82 p.reset(); 83 84 // Make the upcall if required. 85 if (owner) 86 { 87 fenced_block b(fenced_block::half); 88 ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_)); 89 asio_handler_invoke_helpers::invoke(handler, handler); 90 ASIO_HANDLER_INVOCATION_END; 91 } 92 } 93 94 private: 95 Handler handler_; 96 }; 97 98 } // namespace detail 99 } // namespace asio 100 101 #include "asio/detail/pop_options.hpp" 102 103 #endif // ASIO_DETAIL_REACTIVE_SOCKET_CONNECT_OP_HPP 104