user494461
user494461

Reputation:

How to pass io_service object to a new thread using boost::bind?

I have a class called overlay_server which has a public method

void member_list_server(boost::asio::io_service &io_service){

Now I want to run this in a new thread. So I create a new thread, and use bind in its constructor.

Before I was creating an io_service inside the void member_list_server function. But Now I am trying create an io_service object in main and pass it to this thread where i get the error?

  int main(){

    boost::asio::io_service io_service_;

    overlay_server overlay_server_(8002);
    boost::thread thread_(
        boost::bind(&overlay_server::member_list_server, overlay_server_, io_service_)
        );
  1. Why do I get the error

    error C2248: 'boost::noncopyable_::noncopyable::noncopyable' : cannot access private member declared in class 'boost::noncopyable_::noncopyable'

  2. I will create instances of other classes also, which need io_service. What is the best way, should I create one io_service object in main and pass it to all threads?

or create a separate one inside all the threads I create in future?

Upvotes: 2

Views: 4164

Answers (1)

Moshe Rubin
Moshe Rubin

Reputation: 1982

The problem is that you are passing the boost::asio::io_service object by value, rather than by reference. This implies that the boost::asio::io_service default copy constructor should be invoked, something that is not allowed for io_service.

One option is to pass a pointer to the boost::asio::io_service object. Following is some code of mine that does just that:

void Model::TcpPortListener (boost::asio::io_service &io_service, 
                             boost::asio::ip::tcp::acceptor &a, 
                             boost::asio::ip::tcp::endpoint &lep, 
                             SocketObject *readSocketObject)
{
    boost::asio::ip::tcp::acceptor *b = &a;
    boost::asio::io_service *s = &io_service;
    . . .
    boost::asio::ip::tcp::socket *sock (new boost::asio::ip::tcp::socket (io_service));

    a.async_accept (*sock, boost::bind (&Model::HandleRemoteAccept, this, s, b, sock, lep, boost::asio::placeholders::error));
}

void Model::HandleRemoteAccept (boost::asio::io_service *io_service, 
                                boost::asio::ip::tcp::acceptor *a, 
                                boost::asio::ip::tcp::socket *sock, 
                                boost::asio::ip::tcp::endpoint &lep, 
                                const boost::system::error_code& error)
{
    . . .
    // Continue listening
    TcpPortListener (*io_service, *a, lep, 0);
}

The points to observe are:

  1. In Model::TcpPortListener(), 's' is assigned the address of io_service
  2. In the same function, 's' is passed as the third argument to boost::bind(). Since it is an address rather than an object, there's no invocation of the default copy constructor.
  3. In Model::HandleRemoteAccept(), io_service is dereferenced and passed to the TcpPortListener() function.

The point raised by others about dangling references is an important one and should be well accounted for by you.

Upvotes: 1

Related Questions