I was looking at one page of the tutorial of boost::asio.
class tcp_server
{
public:
tcp_server(boost::asio::io_service& io_service)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), 13))
{
start_accept();
}
private:
void start_accept()
{
tcp_connection::pointer new_connection =
tcp_connection::create(acceptor_.get_io_service()); // shared_ptr got created.
acceptor_.async_accept(new_connection->socket(),
boost::bind(&tcp_server::handle_accept, this, new_connection,
boost::asio::placeholders::error)); // instance added to io_service task list, but bind does not use shared_ptr internally I believe.
} // shared_ptr of tcp_connection goes out of scope.
void handle_accept(tcp_connection::pointer new_connection,
const boost::system::error_code& error)
{
if (!error)
{
new_connection->start();
}
start_accept();
}
class tcp_connection
: public boost::enable_shared_from_this<tcp_connection>
{
public:
typedef boost::shared_ptr<tcp_connection> pointer;
static pointer create(boost::asio::io_service& io_service)
{
return pointer(new tcp_connection(io_service));
}
tcp::socket& socket()
{
return socket_;
}
void start()
{
message_ = make_daytime_string();
boost::asio::async_write(socket_, boost::asio::buffer(message_),
boost::bind(&tcp_connection::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
private:
tcp_connection(boost::asio::io_service& io_service)
: socket_(io_service)
{
}
void handle_write(const boost::system::error_code& /*error*/,
size_t /*bytes_transferred*/)
{
}
tcp::socket socket_;
std::string message_;
};
and I found that there's one portion of run time that no shared_ptr
object of tcp_connection
object is alive. That seems to mean that the tcp_connection
object would get destroyed at the beginning of that portion since the count in its shared_ptr
goes down to zero, which is obviously not what we want.
But then I saw the comment in the class tcp_connection
quote
We will use shared_ptr and enable_shared_from_this because we want to keep the tcp_connection object alive as long as there is an operation that refers to it.
And I also did a search for this problem, and got a Q&A in SO here. But I am still puzzled by the titled question. Specifically what does it mean there is an operation that refers to it
? At the time when tcp_server::start_accept()
returns, all shared_ptr
of tcp_connection
instances should go out of scope, and probably only some raw pointer reference was added to the io_service
task list. How does enabled_shared_from_this
prevent the heap instance of tcp_connection
get destroyed when there's no instances of the shared_ptr
of this tcp_connection
object? Or it has nothing to do with enabled_shared_from_this, but the boost::asio::io_service
keeps shared_ptr
of the bounded async_handler internally?