如何使用boost :: bind将io_service对象传递给新线程?

时间:2013-05-24 04:56:39

标签: c++ multithreading boost bind boost-asio

我有一个名为overlay_server的类,它有一个公共方法

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

现在我想在一个新线程中运行它。所以我创建了一个新线程,并在其构造函数中使用bind。

在我在void member_list_server函数中创建io_service之前。 但是现在我正在尝试在main中创建一个io_service对象并将其传递给此线程,我得到错误?

  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. 为什么我会收到错误

    错误C2248:'boost :: noncopyable _ :: noncopyable :: noncopyable':无法访问类'boost :: noncopyable _ :: noncopyable'中声明的私有成员

  2. 我也会创建其他类的实例,这些实例需要io_service。 什么是最好的方法,我应该在main中创建一个io_service对象并将其传递给所有线程吗?

  3. 或在我将来创建的所有主题中创建一个单独的主题?

1 个答案:

答案 0 :(得分:1)

问题是你是按值传递boost :: asio :: io_service对象,而不是通过引用传递。这意味着应该调用boost :: asio :: io_service默认的复制构造函数,这是io_service不允许的。

一个选项是将指针传递给boost :: asio :: io_service对象。以下是我的一些代码:

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);
}

要注意的要点是:

  1. 在Model :: TcpPortListener()中,'s'被分配了io_service的地址
  2. 在同一个函数中,'s'作为boost :: bind()的第三个参数传递。由于它是一个地址而不是一个对象,因此不会调用默认的复制构造函数。
  3. 在Model :: HandleRemoteAccept()中,取消引用io_service并将其传递给TcpPortListener()函数。
  4. 其他人提出的关于悬挂参考文献的观点是一个重要的观点,应该由你充分考虑。