I'm a Boost C++ newbie and, using it to write a Server-like application I am wondering if it is possible to concurrently use boost::asio::ip::tcp::socket::async_read_some(...)
and boost::asio::ip::tcp::socket::write_some(...)
.
In my scenario a Connection object listens continuously via:
void Connection::doRead()
{
auto self(shared_from_this());
socket_.async_read_some(boost::asio::buffer(data_rx_, max_length),
[this, self](boost::system::error_code ec, std::size_t length)
{
if (!ec)
{
afterReading(length);
doRead();
}
});
}
At the same time, an asynchronous function callback (running in a different thread) could invoke socket_.read_write
while Connection is "reading".
I've read various Boost::Asio docs but this scenario was never covered.
Is this allowed? What should be done to avoid it if not?
EDIT:
I have read, as suggested, various answers including this: Why do I need strand per connection when using boost::asio?, but still can't find an answer as it is not specified wether mixing async and sync (called by different threads) calls is safe or not.
It is not safe.
This answer goes into details, but to summarize, it is not safe for multiple threads to make calls concurrently, with the exception that multiple synchronous calls may be safe if supported by the OS. If one thread initiates an asynchronous operation on a socket while another thread is performing a synchronous operation on the same socket, then it falls into the former case and is not safe.
The most elegant solution is to avoid mixing synchronous and asynchronous operations.
strand
to prevent concurrent invocation of handlers.Also, one can synchronously block waiting for an asynchronous operation to complete by leveraging Boost.Asio's support for futures. This approach can allow for one to expose a synchronous blocking API to a user, but use asynchronous operations internally. The initiating operation (async_*
) would need to be invoked within a strand, and if the caller is not running within the context of the strand, then some form of synchronization will need to be used to allow the caller to wait for Asio to create the future object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With