【后台开发拾遗】异步代码同步化

在当今的编程世界中,异步编程已经成为了一种习惯。传统的同步阻塞编程,虽然处理流程非常清晰,但是程序常常处于阻塞等待状态,CPU资源利用率低。而早期的异步编程,通过callback的方式进行回调处理,当回调嵌套开始多起来的时候,程序代码可读性变得非常差。
对于C++,协程和Future/Promise的出现,使得我们既可以实现异步编程,又可以将代码写得十分优美,看起来跟同步代码一般清晰。

本文再次回顾总结下Future/Promise的技术原理,并在最后给出一种编码方式供参考。

相关文章

关于Future/Promise,之前我已经陆陆续续介绍过一些了,本次不会过多的去介绍实现细节,而是从宏观的角度来剖析其原理。

C++11 多线程 future/promise简介

C++异步调用利器future/promise实现原理

总览

Promise主要的类关系如下:

这里写图片描述

由于Future< T >需要针对void进行特化,为避免过多重复的代码,把与特化无关的部分抽离出来形成FutureBase作为基类。

可以看到,Future< T > 和 Promise< T >都有一个同样类型的成员变量:

SharedPtr<detail::FutureObjectInterface<T> > m_future;

m_future是一个引用计数的智能指针。

Promise对象可保存T类型的值,通过Promise的getFuture()方法,产生一个Future对象,此时Promise对象和Future对象内的m_future指向同一个地址,因此Promise对象中保存的T类型的值可被future对象读取(可能在另一个线程中),这是promise提供的同步手段。

类FutureObjectInterface是一个虚类,为Future 和 Promise 提供了m_future的接口。其具体实现包括PromptFutureObject和FutureObject两个类。

Promise的FutureObjectInterface 是一个FutureObject。
Future的FutureObjectInterface有两种情况:直接用一个值来构造Future时(比如调用makeFuture来获取一个future)用的是PromptFutureObject,而其他情况(比如通过Promise获得的future)用的是FutureObject。比如对于使用立即数构造Future时,由于其值已经设定了,不需要等待promise填值进去,因此该future内部的PromptFutureObject是只读的,也就不需要加锁。如果还是使用FutureObject这个版本,将会在加锁解锁上做无用功。因此PromptFutureObject是针对这种场景进行优化的。而当Future 与Promise共享同一个m_future时,由于Future和Promise可能在不同线程中,因此可能同时读写,这里存在race condition,因此需要加锁。FutureObject正是一个加锁的版本。

设置回调——then

上一节我们已经知道,Future< T > 和 Promise< T >共享了值T的状态,假设我们有一个函数:

bool isBlack(string qqNumber);

该函数请求远程服务,来判断该qq号码是否在黑名单内。

那么我们可以如下进行异步调用:

// 1. 定义一个Promise:
promise::Promise< bool > promise;

// 2. 定义一个Callback对象,构造时接收一个Promise对象:
CallBack cb(promise);

// 3. 注册cb(当isBlack函数返回时,通过cb,调用promise的setValue方法对m_future内保存的bool值进行赋值)

// 4. 使用promise的getFuture方法产生一个Future< bool >对象,该Future对象与Promise 共享 m_future。
return promise.getFuture();

于是当isBlack调用返回时,我们通过future.get()即可获取其返回值。

get()属于阻塞函数,它会等待Promise调用setValue()对其承诺的值进行赋值后,方可把值取出来消费。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值