2

In boost async-tcp-echo-server example there is a server class which creates a session on a new connection:

acceptor.async_accept(socket, [this](boost::system::error_code ec) {
    if (!ec)
        std::make_shared<session>(std::move(socket))->start();
    do_accept();
});

session::start() function body:

void start() { do_read(); }

session::do_read method is a private member function:

void do_read()
{
    auto self(shared_from_this());
    socket.async_read_some(boost::asio::buffer(data, sizeof(data)),
        [this, self](boost::system::error_code ec, std::size_t length) {
            if (!ec)
                do_write(length);
    });
}

Please, correct me if I am wrong.
The session class inherits from std::enable_shared_from_this so a control block is already created when calling shared_from_this() and no undefined behavior will occur. In the do_read function shared_from_this() function is used to allow do_write() method to be called on object which still exists in memory. If shared_from_this() wouldn't be used the object could be deleted when reaching end of scope.

Why is this captured in lambda expression?
Is do_write() method called on this or self?

In C++14 could I replace:

auto self(shared_from_this());
socket.async_read_some(boost::asio::buffer(data, sizeof(data)),
    [this, self] ...

with:

socket.async_read_some(boost::asio::buffer(data, sizeof(data)),
        [this, shared_from_this()] ...

? Or even with that:

socket.async_read_some(boost::asio::buffer(data, sizeof(data)),
    [self = shared_from_this()](boost::system::error_code ec, std::size_t length) {
        if (!ec)
            self->do_write(length);
});  

?

Blacktempel
  • 3,935
  • 3
  • 29
  • 53
K. Koovalsky
  • 596
  • 4
  • 17

1 Answers1

5

The self object is captured into the lambda as an ownership token: as long as the lambda lives, the token lives, and the object won't be destroyed.

Capturing this is redundant here, but without it one would have to write

if (!ec)
    self->do_write(length);

instead of

if (!ec)
    do_write(length);

which is the same as

if (!ec)
    this->do_write(length);

Thus, this is captured mainly for readability.

lisyarus
  • 15,025
  • 3
  • 43
  • 68