Boost logo

Boost Users :

Subject: Re: [Boost-users] boost::asio::asyn_accept handler
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2017-03-27 23:20:49


On 28/03/2017 08:56, Christopher Pisz wrote:
> I am looking at the example source at
> http://www.boost.org/doc/libs/1_62_0/doc/html/boost_asio/tutorial/tutdaytime3/src.html
>
> It passes their own connection class to the accept handler as an argument:
>
> acceptor_.async_accept(new_connection->socket(),
> boost::bind(&tcp_server::handle_accept, this, new_connection,
> boost::asio::placeholders::error));
>
> I tried to implement a class method that would do the same:
>
> void ServerSocketASIO::Listen(boost::asio::ip::tcp::acceptor & acceptor,
> std::function<void(ServerSocketASIO *, const boost::system::error_code
> &amp;)> callback)
> {
> acceptor.async_accept(m_socket, callback);
> m_connectionState = LISTENING;
> }
>
> but when I compile, I get errors that say AcceptHandler type requirements
> not met

Your version is not the same.

Consider the bind call in the tutorial: it takes a method which accepts
three parameters and binds two of them, producing a functor that accepts
a single error_code argument, which is what is actually passed to
async_accept.

In your case you are trying to pass a function that takes two parameters
to async_accept, which is incompatible. (You're also not actually
providing any value for that first parameter.)

You either need to use bind() as the tutorial does to provide a value
for the function's first parameter, eg:

void ServerSocketASIO::Listen(boost::asio::ip::tcp::acceptor & acceptor,
const std::function<void(ServerSocketASIO *, const
boost::system::error_code&)>& callback)
{
     acceptor.async_accept(m_socket, boost::bind(callback, this,
boost::asio::placeholders::error));
     m_connectionState = LISTENING;
}

Or you need to use a lambda that does the equivalent:

void ServerSocketASIO::Listen(boost::asio::ip::tcp::acceptor & acceptor,
const std::function<void(ServerSocketASIO *, const
boost::system::error_code&)>& callback)
{
     acceptor.async_accept(m_socket,
         [=](const boost::system::error_code& ec)
             { callback(this, ec); });
     m_connectionState = LISTENING;
}

Alternatively you might want to consider having the callback be a member
method as shown in the tutorial as this usually provides better
encapsulation. (You'll still need to bind it though.)

Another thing to possibly be careful of is the order of statements
inside Listen -- depending on several factors, it's possible for the
callback to be called before m_connectionState is assigned, which might
surprise other logic in your class. Consider assigning it before the
call to async_accept.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net