The last days, I read alot through the asio examples and other questions here on SO regarding lifetime management of buffers passed to asios initiating functions. One issue that strikes me, is that there seems to be no "by value" solution, but instead the caller of the initiating function always needs to ensure that the buffers are valid until the async operation completes. Often this is achieved by creating shared pointers to the data and copying them into the handlers.
In my case I am already using the async_write
overload where a ConstBufferSequence
is passed in which holds e.g. the sizeof the next message followed by the next message. I.e.
auto message = std::make_shared<std::string>("hello");
auto size = std::make_shared<std::uint32_t>(message.size());
std::vector<asio::const_buffer> buffers = {asio::buffer(size, sizeof(*size)), asio::buffer(*message)};
asio::async_write(_socket, buffers, [message,size](...){...}); // prolong lifetime by coping shared ptrs.
So I was thinking about writing a custom Message
class that fulfills the ConstBufferSequence
concept but also owns the underlying message. I dug a little into the code, and found, that at one place the buffer sequence argument, which is at first passed into asio::async_write
via const&
gets passed along via const&
until it finally is copied into a member variable of the asio::detail::write_op
class.
So here the actual question(s):
Can this approach work for a fire and forget call? This would translate above intos something like:
asio::async_write(_socket, Message("hello"),[](auto,auto){});
Are there any issues with the lifetime of the constbuffer sequence arguments w.r.t. composed operations?
Would this be a good idea? It obviously goes against the "normal" asio way of dealing with buffer lifetime management.
Curious about your thoughts - Criticism welcome! ;-)
Regards, Martin