chriskohlhoff / asio

Asio C++ Library
http://think-async.com/Asio
4.97k stars 1.22k forks source link

tls server strand thread safety question #1555

Closed Chrys4lisfag closed 1 week ago

Chrys4lisfag commented 2 weeks ago
static boost::asio::awaitable<void> tcp_listener( boost::shared_ptr<boost::asio::ssl::context> ctx )
{
    // ctx::io_ctx boost::asio::thread_pool with multiple threads
    boost::asio::ip::tcp::acceptor acceptor( ctx::io_ctx->get_executor() );

    // setup acceptor

    while ( true )
    {
        const auto strand = boost::asio::make_strand( ctx::io_ctx->get_executor() );
        auto socket = co_await acceptor.async_accept( boost::asio::bind_executor( strand, boost::asio::deferred ) );
        auto client = std::make_shared<tcp_session>( std::move( socket ), ctx );

        boost::asio::co_spawn( strand,
                       [client_ = std::move( client )] { return client_->start(); },
                       boost::asio::detached );
    }

}

// setup ssl stream
tcp_session::tcp_session( boost::asio::ip::tcp::socket&& _socket,
                          boost::shared_ptr<boost::asio::ssl::context> ctx )
    : stream_( std::move( _socket ), *ctx )
{
}

boost::asio::awaitable<void> tcp_session::start()
{
    // handshake and other stuff

    boost::asio::co_spawn( stream_.get_executor(),
                       [self = this->shared_from_this()] { return self->reader(); },
                       boost::asio::detached );

    boost::asio::co_spawn( stream_.get_executor(),
                        [self = this->shared_from_this()] { return self->writer(); },
                        boost::asio::detached );
}

boost::asio::awaitable<void> tcp_session::reader()
{
    while ( true )
    {
        const auto n =  co_await stream_.async_read_some( buffer, boost::asio::bind_executor( stream_.get_executor(), boost::asio::deferred ) );
    }
}

boost::asio::awaitable<void> tcp_session::writer()
{
    while ( true )
    {
        const auto task = co_await send_channel_.async_receive( boost::asio::deferred );

        const auto n = co_await boost::asio::async_write( stream_, type, boost::asio::bind_executor( stream_.get_executor(), boost::asio::deferred));
    }
}
  1. I used token created from strand to accept socket. Is my future stream_.get_executor() protected by strand is was created from?
  2. Or should I create strand from stream executor in session ctr and use it for coros createtion and\or read\write ops?
  3. I create reader\writer coros using stream executor. If they are protected by stream strand, should I implicitly specify token created from stream when awaiting async_read\write or I can juse use default one?

Thank you for helping me understanding strand usage!