NRaj
NRaj

Reputation: 77

ASIO handler arguments and boost::bind, compile time error

I am struggling with compile time errors, and try as I might, I dont see in what way am I doing it wrong or different from handler function signature as set out in documentation/examples. (I am using Boost 1.41 on Linux)

Please help me understand the error! (included below as snippet)

My application has objects whose methods are handlers for async_* functions. Below is the code snippet. The error is reported in the line labelled as "line 58", where I use boost::bind

class RPC {

public:
    char recv_buffer[56];

    void data_recv (void) {
        socket.async_read_some (
                boost::asio::buffer(recv_buffer),
                boost::bind ( &RPC::on_data_recv, this, _1, _2 )
        );   // **<<==== this is line 58, that shows up in error listing**

        global_stream_lock.lock();
        std::cout << "[" << boost::this_thread::get_id()
            << "] data recvd" << std::endl;
        global_stream_lock.unlock();

    } // RPC::data_recv

    void on_data_recv (boost::system::error_code& ec, std::size_t bytesRx) {
        global_stream_lock.lock();
        std::cout << "[" << boost::this_thread::get_id()
            << "] bytes rcvd: " << std::endl;
        global_stream_lock.unlock();

        data_recv();  // call function that waits for more data

    } // RPC::on_data_recv

};  // RPC class def

There is a huge error output, but the relevant lines seem to be:

../src/besw.cpp:58:   instantiated from here
/usr/include/boost/bind/bind.hpp:385: error: no match for call to ‘(boost::_m    fi::mf2<void, RPC, boost::system::error_code&, long unsigned int>) (RPC*&, boost::asio::error::basic_errors&, int&)’
/usr/include/boost/bind/mem_fn_template.hpp:272: note: candidates are: R boost::_mfi::mf2<R, T, A1, A2>::operator()(T*, A1, A2) const [with R = void, T = RPC, A1 = boost::system::error_code&, A2 = long unsigned int]
/usr/include/boost/bind/mem_fn_template.hpp:291: note:                R boost::_mfi::mf2<R, T, A1, A2>::operator()(T&, A1, A2) const [with R = void, T = RPC, A1 = boost::system::error_code&, A2 = long unsigned int]
make: *** [src/besw.o] Error 1

When I remove the place holders (_1 and _2) and have a handler without arguments, then it compiles and executes without errors. Here's that modified code snippet.

    void data_recv (void) {
    socket.async_read_some (
            boost::asio::buffer(recv_buffer),
            boost::bind ( &RPC::on_data_recv, this )
    );

    global_stream_lock.lock();
    std::cout << "[" << boost::this_thread::get_id()
        << "] data recvd" << std::endl;
    global_stream_lock.unlock();

} // RPC::data_recv

void on_data_recv (void) {
...
}

Upvotes: 1

Views: 82

Answers (1)

sehe
sehe

Reputation: 392911

The error code cannot be taken by reference. Make it by-value or by const&:

void on_data_recv(boost::system::error_code/* ec */, size_t /*bytes_transferred*/) {

Also, consider using the Asio specific placeholders:

    socket.async_read_some(boost::asio::buffer(recv_buffer),
                           boost::bind(&RPC::on_data_recv, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));

Also use proper lock guards. We're in C++! It's easy to make things exception-safe, so why not?

Live On Coliru

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <iostream>

#include <boost/thread.hpp>

static boost::mutex global_stream_lock;

class RPC {
    char recv_buffer[56];
  public:

    void data_recv() {
        socket.async_read_some(boost::asio::buffer(recv_buffer),
                               boost::bind(&RPC::on_data_recv, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));

        boost::lock_guard<boost::mutex> lk(global_stream_lock);
        std::cout << "[" << boost::this_thread::get_id() << "] data recvd" << std::endl;
        global_stream_lock.unlock();
    }

    void on_data_recv(boost::system::error_code/* ec */, size_t /*bytes_transferred*/) {
        {
            boost::lock_guard<boost::mutex> lk(global_stream_lock);
            std::cout << "[" << boost::this_thread::get_id() << "] bytes rcvd: " << std::endl;
        }

        data_recv(); // call function that waits for more data
    }

    boost::asio::io_service service;
    boost::asio::ip::tcp::socket socket{service};
}; // RPC class def

int main() {}

Upvotes: 1

Related Questions