前言
通常来说,有两种异步模式,一种是基于goroutine
的用户态协程并发模型,另一种是基于Future/Promise
的并发模型。后者可能将多个Future
串联,改善回调天堂这一状况。其实Javascript
早就提供了Promise
模型,异步基于事件循环来做,每次都是将异步事件插入工夫序列期待下一次调用。而像C++/Rust
这些语言就必须通过额定的executor
库就安顿异步事件的执行。Rust
中曾经有了十分优良的异步运行时tokio
,Folly
的实现该当是差不多的。
对Folly
的介绍基于自底向上进行的办法,从底层building block
到下层高级原语。
Core
KeepAlive and Deferred
KeepAlive
是对executor
的平安援用,保障不会在KeepAlive
存活时析构executor
。
Deferred
是尚未设置理论executor
的代理,后续须要注入指定的executor
。
Info flow
Core
保护三种info flow
- producer => consumer:
result
、callback
、executor
、priority
- consumer => producer:
interrupt
、interrupt handler
相似于Linux中的信号,用于勾销或xxcallback
的执行 - lifetime control: 2 ref counts(
attached_
和callbackref_
),管制析构
上面是一张 producer => consumer
的状态转换图,清晰地转换Core
的各种状态以及触发条件。
/// +----------------------------------------------------------------+/// | ---> OnlyResult ----- |/// | / \ |/// | (setResult()) (setCallback()) |/// | / \ |/// | Start ---------> ------> Done |/// | \ \ / |/// | \ (setCallback()) (setResult()) |/// | \ \ / |/// | \ ---> OnlyCallback --- |/// | \ or OnlyCallbackAllowInline |/// | \ \ |/// | (setProxy()) (setProxy()) |/// | \ \ |/// | \ ------> Empty |/// | \ / |/// | \ (setCallback()) |/// | \ / |/// | --------> Proxy ---------- |/// +----------------------------------------------------------------+
模块设计
Core
分为CoreBase
和Core<T>
,将与模板无关的信息集中在Core<T>
中。
生命周期治理
因为设计了代理机制,this能够代理其余core
对象,因而,应用attached_
反映援用计数。
另外应用callbackRef_
反映lambda
的援用计数。
为什么显式的应用援用计数而不是智能指针呢?
doCallBack设计
对于某些非凡状况,doCallBack
能够inline
执行callback
函数(也就是在setResult
时间接执行callBack
函数)。
Barrier
这是一个常见的CountDownLatch
或WaitGroup
(前者更适合)的同步原语,返回的所有Promise
会在最初一个wait
调用后被"resolve"
。值得一提的是,外部实现用一个atomic_64
保护两个atomic_32
状态,别离记录以后正在调用wait
的数量和所有曾经调用的数量。当前者 == 0 && 后者 == size 时,进行变量析构、内存开释。
同时,处于性能优化的思考,构造体设计采纳了变长数组 + 定位new。
struct ControlBlockAndPromise { ControlBlock cb; BoolPromise promises[1];};
Promise
Future
和Promise
的一个典型利用如下
/// auto [p, f] = makePromiseContract(executor);/// g = std::move(f).then([](MyValue&& x) {/// ...executor runs this code if/when a MyValue is ready.../// });/// ...launch the async producer that eventually calls p.setResult()...
Future
SemiFuture vs Future
SemiFuture
没有指定executor
,通过.via
指定executor
变身为future
。