I once wrote the the code snippet below to asynchronously send tcp data.
void Conversation::do_write(std::string str)
{
auto conversation_ptr(shared_from_this());
m_socket.async_send(asio::buffer(str), [this, conversation_ptr](std::error_code error, size_t length ){
if (!error)
{
std::cout << "data write successfully" << std::endl;
}
else
{
std::cout << "error in writing data: " << error.message() << std::endl;
}
});
}
Later, I found there is something wrong with the code above. As per the document, which says that the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.
basic_raw_socket::async_send (1 of 2 overloads)
Start an asynchronous send on a connected socket.
template<
typename ConstBufferSequence,
typename WriteHandler = DEFAULT>
DEDUCED async_send(
const ConstBufferSequence & buffers,
WriteHandler && handler = DEFAULT);
This function is used to send data on the raw socket. The function call will block until the data has been sent successfully or an error occurs.
Parameters
buffers
One or more data buffers to be sent on the socket. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.
To keep the context alive, I rewrite the code as blow.
//Note: the passed string would be modified to avoid copying
void Conversation::do_write(std::string& str) //modification1: using the reference
{
auto conversation_ptr(shared_from_this());
//modification2 using shared pointer to keep the content to be sent alive when the handler is called
std::shared_ptr<std::string> content_ptr=std::make_shared<std::string>(std::move(str));
m_socket.async_send(asio::buffer(*content_ptr), [this, conversation_ptr, content_ptr](std::error_code error, size_t length ){
if (!error)
{
std::cout << "data write successfully" << std::endl;
}
else
{
std::cout << "error in writing data: " << error.message() << std::endl;
}
});
}
Is there any better way? How to imporve the code above?