2019年底,Rust正式支持async/await语法,完成了Rust协程拼图的最后一块,让异步代码可以像Go一样简洁地写出来。不过对于程序员来说,了解async/await的实现原理还是很有必要的。async简单地说,async语法生成一个实现Future的对象。以下异步函数:asyncfnfoo()->{...}async关键字修改函数的原型以返回Future特征对象。然后将执行结果包装在一个新的future中返回,大致相当于:fnfoo()->implFuture{async{...}}更重要的是,异步代码块会实现a包装生成器的匿名Future特征对象。即一个实现了Future的Generator。Generator其实就是一个状态机。使用.await,每次async代码块中返回Poll::Pending时,都会调用generatoryield放弃执行权。一旦恢复执行,生成器resume将继续执行流程的其余部分。下面是这个状态机Future的代码:pubconstfnfrom_generator(gen:T)->implFuturewhereT:Generator,{structGenFuture>(T);impl>!UnpinforGenFuture{}impl>FutureforGenFuture{typeOutput=T::返回;fnpoll(self:Pin<&mutSelf>,cx:&mutContext<'_>)->Poll{letgen=unsafe{Pin::map_unchecked_mut(self,|s|&muts.0)};matchgen.resume(ResumeTy(NonNull::from(cx).cast::>())){GeneratorState::Yielded(())=>Poll::Pending,//当代码不能继续执行,放弃控制,返回Pending,等待唤醒GeneratorState::Complete(x)=>Poll::Ready(x),//执行完成}}}GenFuture(gen)}你可以看到这个一个特殊的Future通过Generator运行。每次gen.resume()都会依次执行asyncblock中的代码,直到遇到yield。async块中的.await语句在无法立即完成时会调用yield交出控制权,等待下一次resume。而当所有的代码都执行完,也就是状态机进入Complete,asyncblock返回Poll::Ready,也就是Future执行完成。await每个await本身就像一个执行器,循环查询Future的状态。如果返回Pending,则yield,否则退出循环,结束当前Future。代码逻辑大致如下:loop{matchsome_future.poll(){Pending=>yield,Ready(x)=>break}}为了更好的理解async/await的原理,我们看一个简单的例子:asyncfnfoo(){do_something_1();some_future.await;do_something_2();}async修饰的异步函数foo被重写为一个Generator状态机驱动的Future,里面有一个some_future.await,穿插do_something_x()等其他操作。执行foo().await时,先完成do_something_1(),然后执行some_future.await。如果some_future返回Pending,这个Pending转为yield,所以顶层的foo()也暂时返回Pending。下次唤醒后,foo()调用resume()继续轮询some_future,如果some_future返回Ready,说明some_future.await完成,则foo()开始执行do_something_2()。这里的重点是,因为有状态机的控制,当foo()再次被唤醒时,do_something_1()不会重复执行,而是会从上次yield的地方继续执行some_future.await,相当于完成了一次任务切换,这就是stackless协程的工作方式。总结async/await通过一个状态机来控制代码的流向,配合Executor完成协程的切换。之后写异步代码就不需要手动写Future和它的poll方法了,尤其是异步逻辑的状态机也由async自动生成,大大简化了程序员的工作。虽然async/await出现的时间并不长,但纯粹使用async/await编写的代码目前还不是主流,但我们可以乐观地期待未来会有更多的项目使用这种新语法。参考Futuresin200LinesofRust作者:谢景伟,人称“刀哥”,20年IT老兵,数据通信网络专家,电信网络架构师,现任Netwarps开发总监。刀哥在操作系统、网络编程、高并发、高吞吐量、高可用等领域有多年的实践经验,对网络和编程方面的新技术有着浓厚的兴趣。深圳市网华科技有限公司(Netwarps),专注于互联网安全存储领域的技术研发与应用,是一家先进的安全存储基础设施提供商。其主要产品包括去中心化文件系统(DFS)、企业联盟链平台(EAC)、区块链操作系统(BOS)。微信公众号:网华
async-await是如何工作的-Rust学习笔记相关文章