2011-07-13 27 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回調。 –