2013-03-17 58 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