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

本文探讨了在异步线程中如何正确处理异常的方法。介绍了std::async和std::promise在异常处理上的机制,包括如何捕获并传递异常,以及如何使用std::current_exception和std::copy_exception来存储异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值