最近和Boost.Asio一起玩了很多。我非常喜欢这个库,因为它提供了一种从当今的多核系统中挤出性能的绝佳方法。
我曾多次问过自己的一个问题,在与Asio进行异步调用时,我认为值得抛弃对象的生命周期/所有权。
我反复遇到的问题是你经常需要“过期”仍然有异步回调的对象。如果在调用回调之前该对象超出范围,则不可避免地会发生一些事情。
为了解决这个问题,我已经将boost::enable_shared_from_this
模板用作大多数基于asio的类的基类。这工作正常,但这有点麻烦:通常这也意味着保护构造函数并向类添加工厂方法以确保所有实例都在shared_ptr中创建。
我只是想知道其他人是如何解决这个问题的。我是最好的方式吗?或者我的Asio.Foo错了吗?
讨论......:)
答案 0 :(得分:2)
使用boost::enable_shared_from_this
几乎就是这样做的。另外,如果需要引用不应保留对象的对象(如果它们是唯一保留的引用),请查看使用boost::weak_ptr
。
使用weak_ptr
的一个很好的例子:我在使用enable_shared_from_this
的套接字类中使用boost::asio
。 boost::asio
框架是唯一通过读写处理程序存储对象的持久引用的东西。因此,当调用套接字的析构函数时,我知道套接字已关闭,我可以在处理程序中“执行操作”以清理该已关闭的套接字。使用套接字的应用程序只有一个weak_ptr
引用,当它想要使用套接字时(通常写入它),它会提升为shared_ptr
。如果套接字消失,可以检查该促销是否失败,尽管套接字的关闭处理程序通常会在发生之前适当地清除所有weak_ptr
引用。
答案 1 :(得分:1)
这种事情并不仅限于Asio。我最近写了一个线程池类(使用Boost :: Thread),它有几乎相同的问题 - 线程会调用创建它们的线程池类来查看接下来要执行的任务,使用普通指针对它来说,如果线程池类在子线程仍在运行的情况下被销毁,程序就会崩溃。我通过在线程池析构函数中的每个线程上调用interrupt
来处理它,然后在让析构函数返回之前等待所有线程退出。
如果我理解你的共享指针解决方案,它似乎也在做同样的事情 - 确保在不再需要之前不能销毁该项目。一个美学上令人愉悦的解决方案。我没有看到任何更好的答案来解决这类问题。