Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why we can reuse a moved socket_ in acceptor_.async_accept?

Reference: https://www.boost.org/doc/libs/1_35_0/doc/html/boost_asio/reference/basic_socket_acceptor/async_accept/overload1.html

boost::asio::ip::tcp::acceptor acceptor(io_service);
...
boost::asio::ip::tcp::socket socket(io_service); 
// you have to initialize socket with io_service first before 
//you can use it as a parameter on async_accept.
acceptor.async_accept(socket, accept_handler);

Reference:

https://github.com/vinniefalco/CppCon2018/blob/master/listener.cpp

listener::  listener(
    net::io_context & ioc,
    tcp::endpoint endpoint,
    std::shared_ptr < shared_state >
    const & state): acceptor_(ioc), socket_(ioc), state_(state) {

// Accepts incoming connections and launches the sessions
class listener : public std::enable_shared_from_this<listener>
{
    tcp::acceptor acceptor_;
    tcp::socket socket_;
...
}

// Handle a connection
void listener::  on_accept(error_code ec) {
    if (ec)
      return fail(ec, "accept");
    else
      // Launch a new session for this connection
      std::make_shared < http_session > (
        std::move(socket_),                    // socket_ is moved here?
        state_) -> run();

    // Accept another connection
    acceptor_.async_accept(
      socket_,                                 // why we still can use it here?
      [self = shared_from_this()](error_code ec) {
        self -> on_accept(ec);
      });
  }

Based on my understanding, std::move(socket_) allows the compiler to cannibalize socket_. In other word, the listener::socket_ originally initialized by socket_(ioc) will become uninitialized.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Question> How can we give an uninitialized socket_ to acceptor_.async_accept?

Thank you

>Solution :

It all depends on the implementation of the types.

We can loosely describe the intent of a move as "the compiler is allowed to cannibalize". But really, for user-defined types we’re going to have to tell it how to do that, exactly.

In language "doctrine" a moved-from object may only be assumed safe to destruct, but in practice many libraries make more lenient guarantees (e.g. keeping all the invariants, or making sure that a moved-from object is comparable to a newly constructed one).

Indeed, ASIO documents this:

Remarks

Following the move, the moved-from object is in the same state as if constructed using the basic_stream_socket(const executor_type&) constructor.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading