void proxy::do_send(const std::string& command, const_buffer buffer, result_handler handler) { if (stopped()) { handler(error::channel_stopped); return; } LOG_DEBUG(LOG_NETWORK) << "Sending " << command << " to [" << authority() << "] (" << buffer.size() << " bytes)"; // Critical Section (protect socket) /////////////////////////////////////////////////////////////////////////// // The socket is locked until async_write returns. const auto socket = socket_->get_socket(); // The shared buffer is kept in scope until the handler is invoked. using namespace boost::asio; async_write(socket->get(), buffer, std::bind(&proxy::handle_send, shared_from_this(), _1, buffer, handler)); /////////////////////////////////////////////////////////////////////////// }
void proxy::handle_send(const boost_code& ec, const_buffer buffer, result_handler handler) { const auto error = code(error::boost_to_error_code(ec)); if (error) LOG_DEBUG(LOG_NETWORK) << "Failure sending " << buffer.size() << " byte message to [" << authority() << "] " << error.message(); handler(error); }
void proxy::handle_send(const boost_code& ec, const_buffer buffer, /*scope_lock::ptr lock,*/ result_handler handler) { ////lock = nullptr; //////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ const auto error = code(error::boost_to_error_code(ec)); if (error) log::debug(LOG_NETWORK) << "Failure sending " << buffer.size() << " byte message to [" << authority() << "] " << error.message(); handler(error); }
////// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv ////// THIS REQUIRES AT LEAST TWO NETWORK THREADS TO PREVENT THREAD STARVATION. ////// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ////// The send subscriber pushes queued writes to the writer instead of having ////// writer pull them from a passive queue. This is less thread-efficient but it ////// allows us to reuse the subscriber and facilitates bypass of subscriber ////// queuing for large message types such as blocks, as we do with reads. bool proxy::do_send(const code&, const std::string& command, const_buffer buffer, result_handler handler) { if (stopped()) { handler(error::channel_stopped); return false; } ////if (ec) ////{ //// log::debug(LOG_NETWORK) //// << "Send dequeue failure [" << authority() << "] " << ec.message(); //// handler(ec); //// stop(ec); //// return false; ////} log::debug(LOG_NETWORK) << "Sending " << command << " to [" << authority() << "] (" << buffer.size() << " bytes)"; ////// Critical Section (protect writer) //////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ ////// The lock must be held until the handler is invoked. ////const auto lock = std::make_shared<scope_lock>(mutex_); // Critical Section (protect socket) /////////////////////////////////////////////////////////////////////////// // The socket is locked until async_write returns. const auto socket = socket_->get_socket(); // The shared buffer must be kept in scope until the handler is invoked. using namespace boost::asio; async_write(socket->get(), buffer, std::bind(&proxy::handle_send, shared_from_this(), _1, buffer, /*lock,*/ handler)); return true; /////////////////////////////////////////////////////////////////////////// }