5

In the ASIO HTTP Server 3 example there is code like this:

void server::start_accept()
{
  new_connection_.reset(new connection(io_service_, request_handler_));
  acceptor_.async_accept(new_connection_->socket(),
      boost::bind(&server::handle_accept, this,
        boost::asio::placeholders::error));
}

void server::handle_accept(const boost::system::error_code& e)
{
  if (!e)
  {
    new_connection_->start();
  }

  start_accept();
}

Essentially, new_connection_ is a member of the server class and is used to pass a connection from start_accept to handle_accept. Now, I'm curious as to why new_connection_ is implemented as a member variable.

Wouldn't it also work to pass the connection using bind instead of a member variable? Like this:

void server::start_accept()
{
  std::shared_ptr<connection> new_connection(new connection(io_service_, request_handler_));
  acceptor_.async_accept(new_connection_->socket(),
      boost::bind(&server::handle_accept, this,
        boost::asio::placeholders::error),
        new_connection);
}

void server::handle_accept(boost::system::error_code const& error, std::shared_ptr<connection> new_connection)
{
  if (!error) {
    new_connection->start();
  }
  start_accept();
}

If so, why does the example use member variables? Is it to avoid the copying involved?

(note: I'm not comfortable with ASIO yet and so there may be a fundamental misconception here)

Igor R.
  • 14,716
  • 2
  • 49
  • 83
Pubby
  • 51,882
  • 13
  • 139
  • 180

1 Answers1

4

Passing the socket variable inside a function created with std::bind is more or less the same as retaining it as a member variable in the http::server3::server class. Using bind will create temporaries whereas using the member variable will not. I don't think that is a big concern here as the std::shared_ptr is not terribly expensive to copy nor is this code path in the example a performance critical section.

When writing my own applications I find myself using both techniques. If the asynchronous call chain is very long I will typical retain the variables as members to simplify the handler's function signatures and prevent code repetition. For shorter call chains, keeping the state variables in the functor created from bind is a bit easier to understand the code's logic.

Community
  • 1
  • 1
Sam Miller
  • 23,808
  • 4
  • 67
  • 87
  • 2
    I often use both techniques as well, and follow the same approach as Sam. Additionally, if a type if expensive to copy or the variable is used in multiple chains, then I prefer to use a member variable regardless of the length or simplicity of the individual call chains. – Tanner Sansbury Apr 29 '13 at 15:16
  • Is it a bug to 'use a class member variable'? Because if there is second client connect to the server before calling the server::handle_accept of first client, it will change the value of 'member variable new_connection_' of first client. I am new to boost asio. Maybe I am wrong. – PokerFace Mar 21 '18 at 16:59