【问题标题】:How to pass io_service object to a new thread using boost::bind?如何使用 boost::bind 将 io_service 对象传递给新线程?
【发布时间】:2013-05-19 15:17:32
【问题描述】:

我有一个名为 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 对象并将其传递给所有线程吗?

或者在我将来创建的所有线程中创建一个单独的线程?

【问题讨论】:

  • 你有一些不可复制的东西,并且 bind 打算复制它。根据 boost::bind 的文档,您可以使用 boost::ref 或 boost::cref 来解决这个问题,但要注意悬空引用的典型危险。
  • 另外,绑定 boost:ref(io_service) 后,注意io_service 必须比线程长,否则会有一个悬空引用。所以io_service 不能像你的例子那样是本地的。
  • 为什么不让io_service成为所有线程都可以访问的类成员呢?这就是我所做的。

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


【解决方案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() 函数。

其他人提出的关于悬空引用的观点很重要,你应该好好解释一下。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-11
    • 2015-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多