4

I'm using the latest ASIO version(as of this time 1.18.0). Currently designing a multithreaded asynchronous TCP server with timers(for timeouts). I have a single io_context with multiple threads calling its run() function. I accept new connections like this:

void Server::AcceptConnection()
{
    acceptor_.async_accept(asio::make_strand(io_context_),
            [this](const asio::error_code& error, asio::ip::tcp::socket peer) {
                if (!error) {
                    std::make_shared<Session>(std::move(peer))->run();
                }
                AcceptConnection();
            });
}

And here a stripped down version of the Session class:

class Session : public std::enable_shared_from_this<Session>
{
public:
    Session(asio::ip::tcp::socket&& peer) : peer_(std::move(peer)) {}
    void run()
    {
        /*
        asio::async_read(peer_, some_buffers_, some_callback_);
        timeout_timer_.expires_after();
        timeout_timer_.async_wait();
        // etc
        */
    }
    
private:
    asio::ip::tcp::socket peer_;
    asio::steady_timer timeout_timer_{peer_.get_executor()};
}

Please note the initialization of the timer. Also, beware that I'm not using any kind of strand::wrap() or asio::bind_executor() wrappers for the async handlers of the socket and the timer, because of what I understood, they are no longer required if I initialize my objects with the proper executors.

The question here is: Is that a correct way of handling TCP connection inside a strand with a timer inside the same strand that the TCP connection is using?

Note: The timer is used to abort the TCP connection if the timeout passes.

The Storm
  • 71
  • 8
  • 1
    If ever there was a question that deserved an upvote, it's this one. It's hard to understand why this simple technique isn't in the examples, but if it's there, I sure can't find it. – Allan Bazinet Feb 04 '22 at 23:50

1 Answers1

5

Yes, this is the way I write the things as well, using the new interfaces.

I remember having the same concerns when I started out using the new interface, and ended up checking that the various completion handlers do run on the expected strand, which they do.

All in all, these result in significant simplifications in library usage.

sehe
  • 374,641
  • 47
  • 450
  • 633
  • This does indeed eliminate just a mountain of complexity from the usage. Strange that it's not better documented, really. – Allan Bazinet Feb 04 '22 at 23:52
  • @AllanBazinet The only way to "better" document is by detailing how it was (not uniform) and how it has become as a change. That's bound to generate more confusion. IMO the "design/why" sections of the documentation are very under-appreciated (e.g. [here](https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/overview.html)) and there is of course the [changelog](https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/history.html#:~:text=Added%20support%20for%20the%20proposed%20standard%20executors). I do think that some better "news feed" is very welcome. – sehe Feb 05 '22 at 12:27
  • thanks for clarifing it. I think that how-to examples are missing in the documentation. In particular, before-after examples. Smashing my head to get the new idea... mostly done, thanks to you both too :) – Sigi Mar 08 '23 at 10:57