2016-05-31 40 views
3

是否可以從std::packaged_task創建std::future,它在單獨的線程上執行,但並不總是檢索其結果?從來沒有從std :: packaged_task中檢索std :: future的結果是否安全?

#include <future> 
#include <thread> 

class Result { 
    Result() {} 
    ~Result() {} 
}; 

void foo() { 
    std::packaged_task<Result()> task(..); 
    auto future = task.get_future(); 
    std::thread thread(std::move(task), ...); 
    thread.detach(); 
    if (future.wait_for(std::chrono::milliseconds(timeout_ms)) == std::future_status::ready) { 
    auto result = future.get(); <--- Task didn't take too long, retrieve future result 
    ... 
    } 
} <--- Task is taking too long, just abort and never call future.get() 

它似乎在鏘/的libC++工作:~Result()std::packaged_task閹羊叫上返回的結果還是不get()最終呼籲std::future,但因爲我無法找到在C++約文檔什麼這種使用模式,我想確保它的官方支持。

回答

0

這取決於....你認爲你的程序安全。
爲您顯示的情況下,它是安全的,因爲在:

  • future上做get之前被銷燬它不會阻止。如果未來是使用std::async創建的,並且在它被銷燬之前沒有對其調用get,它將被阻止直到結果可用。
    查看更多關於這個在這裏:http://en.cppreference.com/w/cpp/thread/future/~future

這些行動不會阻止的共享狀態準備就緒, 不同之處在於,如果以下所有條件都爲真,可能會阻止:共享 狀態是通過調用std :: async創建,共享狀態尚未準備好,並且這是對共享狀態的最後一個引用。

現在,如果Result類持有非擁有內存(無論出於何種原因)或某些其他需要手動釋放的資源,該怎麼辦。在這種情況下,你的代碼的正確性就成了問題。要做的更好的事情是將其分派到某個後臺線程以執行緩慢移動的任務。

+0

的確,我注意到了'std :: async'的阻塞行爲,這就是爲什麼我切換到'std :: packaged_task'。我不確定你的代碼的正確性是什麼意思?只要'〜Result()'保證被共享狀態調用,那麼會出現什麼問題呢? – Pol

+0

事實上,如果您的Result類被設計爲擁有內存,那麼您是正確的。但很少情況下,您將不得不保留非擁有數據。在這種情況下忘記調用'get_future'將是不正確的。如果它的目的是完成的(如你的例子),那麼如果資源由RAII處理,可能就好了。 – Arunmu

相關問題