2011-07-13 29 views
2
挂起的异步操作的

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

现在,如果我删除的对象,它将,当然,仍然收到一个回调在一个优秀的套接字操作与“操作中止”错误代码。

的问题:有没有办法强制所有操作的同步完成时,我与它拥有短耳对象(插座,定时器)一起删除的对象?

回答

1

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

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

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

因此,在回调中使用弱指针,让回调以weak_ptr作为参数,调用wp.lock(),检查它,如果它仍然有效,则对其进行解引用。在清除主shared_ptr和调用wp.lock()的另一个线程(假设您有多个线程)的情况下,仍然会出现争用情况,但您可以通过在对象中使用标记来解决此问题。

更新与响应发表评论:

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

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

  1. 通过使用一些额外的数据结构来检测该对象已被删除。这是shared_ptr/weak_ptr在内部执行的操作,您可以自由构建自己的等效项。

  2. 等待一切完成,然后删除该对象。不需要使用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; 
} 

什么调用cancel_outstanding_operations()做,如果调用的OBJ :: io_done()过程中的另一个线程?它是否等待它返回,还是因为I/O操作完成而立即返回?在“立即返回”的情况下,“delete o”语句并不安全。在“等待它返回”的情况下,除了已经添加了一堆实现复杂性并且必须同步执行等待外,您还有上面的“等待所有事情完成”的情况。

+2

是的我明白我可以使用weak_ptr,但假设我不能。似乎很愚蠢的是,没有安全的方法来取消未使用shared_ptr的挂起操作。事实上,似乎Asio *强制我使用共享/弱指针进行异步回调,而不会留下任何摆动空间。更糟的是,这迫使我对一个对象有一种“limbo”状态,当它从应用程序逻辑的角度来看不再有效时,但仍然可以接收到一个Asio回调。 –