1 个不稳定版本
0.1.0 | 2023年12月23日 |
---|
#219 in 无标准库
22KB
181 行
此 crate 将 async-let 实现为一个 #[no_std]
,无安全风险,无恐慌,开销最小的库。
Async-let 是基于康拉德·卢德盖特从 https://conradludgate.com/posts/async-let 的想法进行的实验,它提出了一种语法,允许 futures 在不启动额外任务的情况下“在后台”运行。async-let 的一般行为是,以下(虚构的)语法
async let metadata = client.request_metadata();
将 future 标记为后台 future。绑定和 data.await
之间的任何 await 点都将轮询 data
以及被等待的 future。
// `metadata` is marked as a background future here
async let metadata = client.request_metadata();
// both `data` and `metadata` are polled while awaiting `data`
let data = client.request_data().await;
// unmark `metadata` as a background future and await it
let metadata = metadata.await;
使用此 crate 的 API,上述内容可以写成这样。
// create a group that will drive the background futures
let group = async_let::Group::new();
// mark `metadata` as a background future by attaching it to the group
let metadata = pin!(client.request_metadata());
let (metadata, group) = group.attach(metadata);
// await `data` using the group, which polls the background futures
let data = group.wait_for(client.request_data()).await;
// detach `metadata` from the group and await it
let (metadata, group) = group.detach_and_wait_for(metadata).await;
API
此 crate 提供的主要类型有 Group<List>
,一种管理驱动静态类型 List
的后台 futures 的类型;以及 Handle<Fut>
,一种抽象的句柄,代表提取类型为 Fut
的后台 future 的能力。attach
方法将 future 添加到后台 futures 的列表中,detach
方法删除 future,而 wait_for
方法产生一个当被轮询时会轮询后台 futures 的 future。
为了最小化跟踪后台 futures 的开销,每个 Group
都关联一组固定的 futures。将 future 添加到组或从组中删除 future 会消耗组,并产生一个新的组,其中包含添加到或从后台 futures 集合中删除的 future。
限制
在追求最小开销的过程中,做出了一些权衡。
- 易用性:虽然 API 被设计得尽可能易用,但调用者仍需要手动添加和删除 futures,在每个操作中通过组传递线程,并显式本地固定 futures。
- 固定:由于一个组将它的未来列表内联存储,所以存储的未来必须是
Unpin
。需要固定的未来必须通过间接引用来存储,例如使用pin!
或Box::pin
。 - 生命周期:当一个未来被附加或分离时,组必然会被移动。如果未来在一个嵌套的作用域中附加,必须在离开该作用域之前将其分离,否则组(及其所有附加的未来)将变得不可访问。
- 分支:由于未来的集合是静态跟踪的,因此如果希望在条件之后组仍然可访问,则不可能仅在条件的某一分支中附加未来。可以通过将附加的未来的类型擦除为
dyn Future<Output = X>
来在组的同一位置附加不同类型的未来,但这有其局限性。
依赖
~46KB