试图理解提升示例httpserver3。使用shared_ptr重置方法时不清楚

时间:2013-09-14 18:50:10

标签: c++ boost shared-ptr httpserver

我正在使用boost示例httpserver3:http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/examples.html#boost_asio.examples.http_server_3

我无法清楚地了解调用new_connection_的重置方法时会发生什么

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();
  }
    std::cout<<"handle_accept"<<std::endl;
  start_accept();
}

我知道“重置”会导致前一个对象被删除,如文档所述。 如果服务器对象在先前的连接对象处理它的请求时接受新连接会发生什么?将先前的连接立即销毁,否则会收到错误并退出?

void connection::handle_read(const boost::system::error_code& e,
    std::size_t bytes_transferred)
{
  if (!e)
  {
    boost::tribool result;
    boost::tie(result, boost::tuples::ignore) = request_parser_.parse(
        request_, buffer_.data(), buffer_.data() + bytes_transferred);

    if (result)
    {
      request_handler_.handle_request(request_, reply_);
      boost::asio::async_write(socket_, reply_.to_buffers(),
          strand_.wrap(
            boost::bind(&connection::handle_write, shared_from_this(),
              boost::asio::placeholders::error)));
    }
    else if (!result)
    {
      reply_ = reply::stock_reply(reply::bad_request);
      boost::asio::async_write(socket_, reply_.to_buffers(),
          strand_.wrap(
            boost::bind(&connection::handle_write, shared_from_this(),
              boost::asio::placeholders::error)));
    }
    else
    {
      socket_.async_read_some(boost::asio::buffer(buffer_),
          strand_.wrap(
            boost::bind(&connection::handle_read, shared_from_this(),
              boost::asio::placeholders::error,
              boost::asio::placeholders::bytes_transferred)));
    }
  }

  // If an error occurs then no new asynchronous operations are started. This
  // means that all shared_ptr references to the connection object will
  // disappear and the object will be destroyed automatically after this
  // handler returns. The connection class's destructor closes the socket.
}

void connection::handle_write(const boost::system::error_code& e)
{
  if (!e)
  {
    // Initiate graceful connection closure.
    boost::system::error_code ignored_ec;
    socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
  }

  // No new asynchronous operations are started. This means that all shared_ptr
  // references to the connection object will disappear and the object will be
  // destroyed automatically after this handler returns. The connection class's
  // destructor closes the socket.
} 

1 个答案:

答案 0 :(得分:1)

啊,shared_from_this()的魔力。你错过了这部分代码:

void connection::start()
{
  socket_.async_read_some(boost::asio::buffer(buffer_),
      strand_.wrap(
        boost::bind(&connection::handle_read, shared_from_this(),
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred)));
}

这是怎么回事:

  1. server::handle_accept()来电new_connection_->start()
  2. connection::start()计划读取操作,并通过这样做,使用shared_from_this()调用创建原始共享指针的副本。
  3. 现在 server::handle_accept()来电server::start_accept()
  4. server::start_accept()执行reset()原始共享指针,但ASIO服务有一份副本,因此只要连接的回调使用shared_from_this()调度更多操作,连接就会赢得'被销毁(因为至少有一个共享指针仍然指向堆分配的connection对象)。