2015-05-29 44 views
5

我已經寫了下面的代碼來測試std::async()函數返回void與Ubuntu上的GCC 4.8.2。std :: async保證被調用返回void的函數嗎?

#include <future> 
#include <iostream> 

void functionTBC() 
{ 
    std::cerr << "Print here\n"; 
} 

int main(void) 
{ 
#ifdef USE_ASYNC 
    auto i = std::async(std::launch::async, functionTBC); 
#else 
    auto i = std::async(std::launch::deferred, functionTBC); 
#endif 
    //i.get(); 
    return 0; 
} 

如果i.get();未被註釋,消息"Print here"總是存在;然而,如果i.get();被註釋掉,"Print here"存在當且僅當USE_ASYNC被定義(即,std::launch::async總是導致消息打印出來,而std::launch::deferred從來沒有)。

這是有保證的行爲嗎?確保執行異步調用void的正確方法是什麼?

+4

如果您要求推遲推出並且從未在未來調用.get,那麼您的函數將永遠不會執行。這與返回void或任何其他類型的函數無關。 – sbabbi

回答

7

std::launch::deferred意思是「不要運行這個,直到我.wait().get()」。

因爲你從來沒有.get().wait()編輯,它從來沒有跑。

void與此無關。

對於std::launch::async,標準規定返回的將來的析構函數(~future)將會阻塞,直到任務完成(即具有隱含的.wait())。這是違反了MSVC的目的,因爲他們不同意這一設計決定,他們正在努力改變標準:在實踐中,這意味着如果您想要面向未來,您不能依賴任何來自std::launch::async返回future的任何行爲你的代碼。

沒有暗示wait~future,它將是不確定的,如果它退出時main實際調用函數。它要麼發生,要麼不發生。可能你可以通過在main末尾仍然有效的線程來調用UB。

您可能想知道deferred有什麼用處:您可以使用它來計算延遲評估的計算。

+0

如果我只是放棄'std :: async()'的返回值(在我的代碼片段中刪除'auto i ='),'std :: launch :: deferred'版本仍然被跳過。這違反了「'〜future」會阻止,直到任務完成「? – timrau

+0

「〜將來會阻塞,直到任務完成」不適用於這種情況,因爲std :: launch :: deferred。建議你拿起Meyer的「Effective Modern C++」副本,見條目38. – kfsone

+1

@timrau關於'〜future'阻塞的注意事項僅適用於'std :: async(std :: launch :: async')的情況。調用'std :: async(std :: launch :: async')而不存儲返回值會導致它在語句結束時被銷燬,所以主線程會阻塞,直到異步任務完成*。將它存儲在'auto i ='中會使得塊出現在範圍的末尾,將返回的'future'移動到另一個'future'將推遲塊,直到存儲狀態的未來最終被銷燬。 – Yakk

相關問題