[C++11 并发编程] 16 在期望中保存异常

来源:互联网 发布:排施工计划软件 编辑:程序博客网 时间:2024/06/11 17:37

如果在异步线程中发生了异常,等待期望的线程如何才能知道并且正确的处理异常呢?

假设有如下所示的一个求平方根的函数:

double square_root(double x){    if(x<0)    {        throw std::out_of_range(“x<0”);    }    return sqrt(x);}

通常,如果在当前线程上下文中调用square_root(),方法如下:

double y=square_root(-1);
在异步线程中调用square_root(),方法如下:

std::future<double> f=std::async(square_root,-1);double y=f.get();
理想情况下,两种方式都能通过y获得函数调用的执行结果。如果发生了异常,能让调用者知道这个异常,就更好了。

实际上,如果在std::async中执行的函数抛出了异常,这个异常将被存储在期望中,期望变为就绪状态,等待get()被挂起的线程将被唤醒,get()函数再次抛出这个存储在期望中的异常。

类似的,std::promise也有类似的功能,只不过需要我们显示的set_exception()接口来设置:

try{some_promise.set_value(calculate_value()); }catch(...){some_promise.set_exception(std::current_exception());}
这里使用std::current_exception()来获取当前抛出的异常。除此之外,还可以使用std::copy_exception()直接产生一个新的异常存放到promise之中:

some_promise.set_exception(std::copy_exception(std::logic_error("foo ")));
在异常类型确定的情况下,推荐使用这种方式,因为这样比起try/catch块不仅更加清晰,编译器在优化代码时,效果也更好。

到此为止,所有的示例代码都在使用std::future,但是std::future也有一定的限制,因为只有一个线程可以等待这个期望的返回。如果有多个线程需要等待同一个事件,我们需要使用std::shared_future。

0 0
原创粉丝点击