我有一个接收来自boost::io_service
的回调的对象,由于一些原因我不能通过共享指针发布回调(是的,我知道它是 官方的处理方式它),所以我用原始指针绑定处理程序。假设在这种情况下这是一个固定的要求。
现在,如果我删除了该对象,它当然仍然会收到一个带有“操作中止”错误代码的未完成套接字操作的回调。
问题:当我删除一个对象及其拥有的Asio对象(套接字,定时器)时,有没有办法强制同步完成所有操作?
答案 0 :(得分:1)
你不能;那时的信息已经丢失了。你甚至无法比较函数对象的相等性,更不用说查看内部并比较一些指针然后决定做什么。
所以,问题是:为什么你不能使用共享指针?
这样做的方法是使用共享指针和弱指针。如果您不想使用共享指针和弱指针,您可以自己实现底层机制。但是,使用库实现通常更可靠。
因此,在回调中使用弱指针,让回调将weak_ptr作为参数,调用wp.lock(),检查它,如果它仍然有效,则取消引用它。仍然会有一个竞争条件,你清除主shared_ptr和另一个调用wp.lock()的线程(假设你有多个线程),但是你可以通过在对象中使用一个标志来解决这个问题。
更新以回复评论:
Asio并没有强迫您使用shared_ptr / weak_ptr组合。您可以自由地构建自己的解决方案,但必须解决相同的问题。
假设你不能使用weak_ptr,一旦你确定没有其他人会使用指针,你应该删除该对象。原则上,您有两种基本方法:
使用一些其他数据结构检测对象已被删除。这就是shared_ptr / weak_ptr在内部执行的操作,您可以自由构建自己的等效文件。
等待所有内容完成,然后删除该对象。没有要求使用shared_ptr / weak_ptr,但你需要以某种方式保存书籍。
在这些情况下,您最终会手动或使用库来跟踪未完成的内容。基本任务是一样的,但您不必使用库。你被迫解决这个普遍的问题。
您要求的方法,同步“取消”每个未完成的操作,以便您可以安全地删除对象,减少到其中一种情况。
考虑:
class Obj {
void queue() { wait_for_io(this, bind(&Obj::io_done, this, _1)); }
void io_done(error_code const& error)
{
// Do stuff.
}
};
void kill_object(Obj* o)
{
cancel_outstanding_operations_for_obj(o);
delete o;
}
如果在另一个线程中调用Obj :: io_done(),对cancel_outstanding_operations()的调用会怎样?是否等待它返回,或者它是否因为I / O操作完成而立即返回?在“立即返回”的情况下,“删除o”语句不安全。在“等待它返回”的情况下,你有“等待一切完成”的情况,除了你已经添加了一堆实现复杂性,你必须同步进行等待。