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

C++ 刷新boost::asio中的所有异步处理程序,c++,boost,asynchronous,boost-asio,C++,Boost,Asynchronous,Boost Asio,我正在运行一些需要异步通信的测试,底层框架是Asio。有时,即使测试已被删除,处理程序仍保留在处理循环中,这是有充分理由的。但是,删除目标后会调用它 测试类: virtual void SetUp() { _client = new Client; _server = new Server; Service::run(); } virtual void TearDown() { Service::stop(); delete _client; delete _ser

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

测试
类:

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

  Service::run();
}

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

  delete _client;
  delete _server;
}
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();
}
服务
类:

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

  Service::run();
}

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

  delete _client;
  delete _server;
}
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\u服务::stop()
是非阻塞的,所以在我的例子中它变得非常无用。如果在函数末尾删除
io\u服务
对象,则不会调用处理程序,但我希望有更好的解决方案,在删除对象之前强制完成

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

我使用Asio(非Boost)1.4.5,但可以考虑升级(以获得<代码> IoService::停止()/<代码>操作)


编辑:添加
io\u服务
包装器代码,因为根据注释它似乎是相关的。

您是否考虑过使用boost::shared\u ptr来管理对象生命周期?在某些情况下,boost::enable_shared_from_这可能很有用。可以找到一个这样的讨论


另一种选择是在调用stop之后加入线程,以确保在删除对象之前调用了处理程序。

我觉得您需要稍微重新考虑一下您的设计<正如您所注意到的,code>io_服务::stop确实是异步的。它会导致对
io\u service::run()
的任何调用尽快返回。在运行
~io\u服务()
析构函数之前,不会使用
boost::asio::error::operation\u调用任何未完成的处理程序。要管理对象生命周期,应使用
共享的\u ptr
,如下所示:

描述了销毁顺序 以上允许简化程序 他们的资源管理是通过使用 共享\u ptr。物体的位置 生命周期与生命周期相关联 连接(或某些其他连接序列) 异步操作),一个共享的 将对象绑定到 所有异步处理程序 与之相关的操作。这 工作内容如下:

  • 当单个连接结束时,所有关联的异步操作 完成相应的处理程序 对象被销毁,所有 对对象的共享\u ptr引用 它们被摧毁了
  • 要关闭整个程序,调用io_服务函数stop() 尽快终止任何run()调用 尽可能的。io_服务析构函数 上述定义将销毁所有处理程序, 使所有共享的\u 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
}

这对于我的环境来说是非常特殊的,但是
shared\u ptr
的想法在这里没有帮助:测试结束后,对象仍然存在,对下一个测试造成了可怕的副作用。唯一允许在测试中幸存下来的对象是
服务
,因为它也在内部用于管理超时和其他内容。也许这不是一个好的做法。你的第二个想法已经实现了,但似乎也没有什么帮助(也许这里也有一些东西需要研究)。好吧,奇怪的是,我会认为如果你在删除对象之前加入线程会起作用,因为加入块。应该从运行io_service::run的线程调用处理程序,因此之后不能/不应该调用任何处理程序。这是预期的行为,其他地方可能有问题。我无法接受在所有处理程序完成之前启动的下一个测试。如果我手动破坏
io\u服务
,我可能会错过一些东西。我已经更新了代码:
\u thread->join()
应该确保调用了所有的处理程序,所以我真的不知道如何在这里获得竞争条件。@Warren加入线程如何防止竞争条件?线程调用
io\u服务::run
,它将在
io\u服务::stop
之后返回。在这一点上,处理程序仍然是优秀的,这就是为什么我发布了
~io_服务
析构函数文档,并建议使用
共享的ptr
管理对象生命周期。