C++ 刷新boost::asio中的所有异步处理程序
我正在运行一些需要异步通信的测试,底层框架是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
测试
类:
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
管理对象生命周期。