《白话C++》第12章并发,Page558 12.4 承诺 取线程的处理结果

用入参的方式从某个线程中,取回处理结果

多了一个入参r,而且是引用方式

编译,会报一大串错误内容,大意是找不到类型为“void(int, int, int)”的函数,原因是test()函数中,我们传递第三个入参r时,没有按calc的要求使用引用,

这时2011年新标的std::ref小工具就派上用场了,

23行,创立了一个线程,

28行,代用trd.join()之后才访问r,以确保线程目标过程确实完成对r的处理。

【危险】:跨线程传递引用对象

使用引用传递对象,自然需要非常小心引用对象的生命周期,因此有时候也会改用指针,当然通常我们使用智能指针。

就算如此,相比高层概念“async/future”的功能,直接使用底层概念thread处理业务逻辑,还有一个大问题没解决:

线程目标函数执行过程中发生异常时,外部调用线程怎么捕获?

第一种做法当然又是“一不做二不休”。我们在线程目标过程中处理完所有异常,保证不向“外太空”抛出异常。

第二种做法是使用标准库的promise工具,然后将该问题转由future来解决。

promise直译就是“承诺

两个巨大的数相加之后,造成一处,应该抛出异常,如何捕获?

通常我们不直接修改现有函数,而是在它的基础上加一层“承诺(promise)”,得到一个带承诺版本的操作:

std::promise<T> 就是T带上承诺以后的类型,依据需要,这里是int类型,当一切顺利,通过p.set_value(V)以设置正常结果;如果发生异常,通过set_exception(E)设置异常。 

这里有个偷懒行为:我们使用“...”捕获任意类型异常,然后通过C++11标准库提供的current_exception()获得当前线程最后一次发生的异常

test()函数中,新线程的目标过程,改为使用calc_with_promise,对应的,第三个入参改为使用带承诺的版本

请注意代码58行,detach()方法调用,使用“承诺”之后,最终是在future对象的get()时等待,因此可以不管线程对象是否执行完毕。当然线程对象的生命周期在取得结果之前,必须有保障。

最后看主函数:

运行结果:

从“线程”小节开始折腾,一直到“承诺”,感觉就是证明了一个定理:thread + promise = async

这个定理不太严谨,但却再次强调了C++11新表并发编程的一个原则:

一般的并发问题,使用“异步”实现已经很够用了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值