在Boost.Asio中阻止取消挂起的异步操作

时间:2011-07-13 04:45:20

标签: c++ boost boost-asio

我有一个接收来自boost::io_service的回调的对象,由于一些原因我不能通过共享指针发布回调(是的,我知道它是 官方的处理方式它),所以我用原始指针绑定处理程序。假设在这种情况下这是一个固定的要求。

现在,如果我删除了该对象,它当然仍然会收到一个带有“操作中止”错误代码的未完成套接字操作的回调。

问题:当我删除一个对象及其拥有的Asio对象(套接字,定时器)时,有没有办法强制同步完成所有操作?

1 个答案:

答案 0 :(得分:1)

你不能;那时的信息已经丢失了。你甚至无法比较函数对象的相等性,更不用说查看内部并比较一些指针然后决定做什么。

所以,问题是:为什么你不能使用共享指针?

这样做的方法是使用共享指针和弱指针。如果您不想使用共享指针和弱指针,您可以自己实现底层机制。但是,使用库实现通常更可靠。

因此,在回调中使用弱指针,让回调将weak_ptr作为参数,调用wp.lock(),检查它,如果它仍然有效,则取消引用它。仍然会有一个竞争条件,你清除主shared_ptr和另一个调用wp.lock()的线程(假设你有多个线程),但是你可以通过在对象中使用一个标志来解决这个问题。

更新以回复评论:

Asio并没有强迫您使用shared_ptr / weak_ptr组合。您可以自由地构建自己的解决方案,但必须解决相同的问题。

假设你不能使用weak_ptr,一旦你确定没有其他人会使用指针,你应该删除该对象。原则上,您有两种基本方法:

  1. 使用一些其他数据结构检测对象已被删除。这就是shared_ptr / weak_ptr在内部执行的操作,您可以自由构建自己的等效文件。

  2. 等待所有内容完成,然后删除该对象。没有要求使用shared_ptr / weak_ptr,但你需要以某种方式保存书籍。

  3. 在这些情况下,您最终会手动或使用库来跟踪未完成的内容。基本任务是一样的,但您不必使用库。你被迫解决这个普遍的问题。

    您要求的方法,同步“取消”每个未完成的操作,以便您可以安全地删除对象,减少到其中一种情况。

    考虑:

    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”语句不安全。在“等待它返回”的情况下,你有“等待一切完成”的情况,除了你已经添加了一堆实现复杂性,你必须同步进行等待。