2013-03-17 79 views
6
std::promise<int> p1; 
auto f = p1.get_future(); 

{ 
    std::promise<int> p2(std::move(pr)); 
} 

bool valid = f.valid(); // true 
f.wait(); // does not throw, or fail, but returns immediately 
f.get(); // throws an exception 

有沒有什麼辦法可以在致電get之前檢查未來是否會拋出?我希望valid會檢查...我真的不知道如何讓valid返回false。銷燬promise而不設置值不會執行此操作。期貨,承諾和例外

+2

'std :: future'可以被看作是std :: promise'狀態的觀察者。如果諾言消失了,未來就是懸崖勒馬。這不是UB,因爲sehe說,但你得到一個'std :: broken_promise'異常,因爲承諾永遠不能滿足。 – Xeo 2013-03-17 23:47:10

+0

一旦您調用'get'或'share'一次,valid將返回false。 – inf 2013-03-17 23:57:11

+1

[future :: valid](http://en.cppreference.com/w/cpp/thread/future/valid)表示「檢查未來是否指向共享狀態」。如果承諾沒有了,價值從未設置,那不是說沒有共享狀態嗎? – David 2013-03-17 23:57:27

回答

5

有沒有什麼辦法可以在撥打 之前檢查未來是否會拋出?

不,因爲這在某種程度上等於接收未來存儲的值。

我希望有效的檢查...我不太確定如何得到有效的 返回false。如果未來是指可以僅通過std::asyncstd::packaged_taskstd::promise創建一個共享狀態

有效將返回true。一個反例是默認構造的std::future。一旦您在有效(有效==真實)未來一次呼叫getshare,有效值也將爲假。
調用除valid之外的任何其他函數或移動賦值運算符對無效(有效==虛假)將來都是UB。

銷燬承諾而未設置值不會執行此操作。

不,如上所述不是有效的點,因爲未來仍然指的是共享狀態只是另一方 - 承諾 - 沒有實現。如果破壞承諾,則不設置任何值或例外,則會設置一個例外來指示已破壞的承諾。

1

有什麼辦法可以在調用get之前檢查未來是否會拋出?

你的問題等同於:
有沒有什麼辦法來檢查,如果功能會調用它之​​前扔?

這兩個問題的答案總的來說不是。

考慮:

int func_that_might_throw() 
{ 
    if (rand() % 2) 
    throw 1; 
    return 0; 
} 

std::future<int> f = std::async(&func_that_might_throw); 

int result = f.get(); 

async調用可以返回一個延遲功能,在這種情況下,功能甚至不運行,直到您叫get(),所以一般是沒有辦法事先知道是否結果將是一個值或一個例外。 (您可以通過調用f.wait_for(std::chrono::seconds(0))來檢測延遲的函數,但async可能不會返回延遲函數,並且在這種情況下,當您嘗試檢查它是否存儲異常時,該函數仍可能異步運行,因此您必須檢查如果它已準備好並且存在異常,那麼檢查就會變得非常混亂。)

一個有效的future具有已準備就緒的共享狀態,其結果可能是值或異常。兩者都是有效的結果。如果你不想處理異常,那麼你應該確保首先不會在共享狀態中設置異常。

+0

未來::得到並不一定有像'if(IsReady())返回值;否則如果(!PromiseExists())拋出:promise;'?因此可能有一個函數返回'!IsReady()&&!PromiseExists()'。我不明白爲什麼這種情況不適合無效(...'valid()== false),但設計師沒有這樣做。 – David 2013-03-18 14:17:58

+0

簡要說一下我的用例:我在每一幀(〜20)中啓動了一堆異步任務(使用我自己的異步隊列,而不是std :: async)。下一幀我想取消任何尚未執行的任務,並推送一組20個可能執行的任務。我希望我的異步隊列在我將工作推向未來時給我一個未來,但如果我不能通過使用未來告訴工作已經取消或不能使用期貨,或者我必須包裹它們。我可以通過調用get和捕獲異常來實現,但這太慢了。 – David 2013-03-18 14:22:46

+0

給你的第一個評論:當諾言消失時,'broken_promise'被設置,而不是當你尋找結果。 'valid()'意味着「共享狀態」,未來仍然有一個共享狀態,就像現在已經多次聲明的那樣。 – 2013-03-18 17:11:21