I have this code from Boost Beast async chat server examples:
void ChatServer::StartAccept() {
acceptor.async_accept(
boost::asio::make_strand(acceptor.get_executor()),
[self = shared_from_this()] (error_code err, tcp::socket socket) {
if (err) return self->Fail(err, "Failed to accept connection");
std::make_shared<HttpSession>(std::move(socket), self->sslContext, self->room)->Start();
self->StartAccept();
});
}
Now I understand that I have to make a separate strand for each connection/socket, because I'm running one io_context in multiple threads. If I don't do that, I could have threads reading/writing from the same socket which is a data race.
However in the example they still use dispatch to the executor associated with the socket, which is strand?
void HttpSession::Start() {
boost::asio::dispatch(
stream.get_executor(),
[self = shared_from_this()]() {
self->DoSslHandshake();
});
}
Why do I have to use dispatch here? Isn't every socket already associated with its own strand?
It's not required, but that's only coincidental. The code expresses intent.
In fact, many of the library examples have an explanatory comment:
I've elaborated on this before more relevant to your context:
Or, similary, but way more brief: