刷新boost :: asio中的所有异步处理程序

时间:2011-04-15 11:07:07

标签: c++ boost asynchronous boost-asio

我正在运行一些需要异步通信的测试,底层框架是Asio。有时,即使测试已经被删除,处理程序也会保留在处理循环中,这是有充分理由的。但是,在目标被删除后,它被称为

Test类:

virtual void SetUp()
{
  _client = new Client;
  _server = new Server;

  Service::run();
}

virtual void TearDown()
{
  Service::stop();

  delete _client;
  delete _server;
}

Service类:

static void run()
{
  _thread = new asio::thread(boost::bind(&asio::io_service::run, _service));
}

static void stop()
{
  _service->stop();

  _thread->join();
  delete _thread;

  _service->reset();
}

io_service::stop()是无阻塞的,因此在我的情况下它变得毫无用处。如果我在函数末尾删除io_service对象,则不会调用处理程序,但是我想要一个更好的解决方案,在删除对象之前强制完成。< / p>

注意:实际的处理循环是在第二个线程中完成的,但它是在io_service::stop()包装器中连接的,整个问题似乎与线程无关。

我正在使用Asio(非Boost)1.4.5,但可以考虑升级(以获得io_service::stopped()操作吗?)。

编辑:根据评论添加io_service包装代码,因为它似乎是相关的。

2 个答案:

答案 0 :(得分:5)

在我看来,你需要稍微重新考虑一下你的设计。正如你所注意到的,io_service::stop确实是异步的。它会导致io_service::run()的任何调用尽快返回。在boost::asio::error::operation_aborted析构函数运行之前,不会使用~io_service()调用任何未完成的处理程序。要管理对象生命周期,您应该使用shared_ptr作为documentation建议:

  

描述的破坏序列   以上允许程序简化   他们的资源管理使用   的shared_ptr&LT;取代。对象的位置   寿命与a的寿命有关   连接(或其他一些序列)   异步操作),一个shared_ptr   将对象绑定到   所有异步处理程序   与之相关的操作。这个   工作原理如下:

     
      
  • 当单个连接结束时,所有关联的异步操作   完成。相应的处理程序   对象被摧毁,所有   shared_ptr对象的引用   被毁了。
  •   
  • 要关闭整个程序,调用io_service函数stop()   尽快终止任何run()调用   尽可能。 io_service析构函数   以上定义会破坏所有处理程序,   导致所有shared_ptr引用   所有连接对象   破坏。
  •   

更具体地说,你有一个竞争条件

virtual void TearDown()
{
  service->stop();

  // ok, io_service is no longer running
  // what if outstanding handlers use _client or _server ??

  delete _client;
  delete _server;

  // now you have undefined behavior due to a dangling pointer
}

答案 1 :(得分:2)

您是否考虑过使用boost :: shared_ptr来管理对象的生命周期?在某些情况下,boost :: enable_shared_from_this可能很有用。可以找到SO讨论here

另一个选项可能是在调用stop后加入线程,以确保在删除对象之前已经调用了处理程序。