4个版本
0.2.2 | 2023年3月25日 |
---|---|
0.2.1 | 2022年2月5日 |
0.2.0 | 2021年9月16日 |
0.1.0 | 2021年4月3日 |
#370 in 异步
18,236 个月下载量
在 43 个crates中使用 (8直接使用)
41KB
584 行
async_cell
本crate的关键类型是 AsyncCell
,它提供线程安全和单线程两种变体。它被设计为一个有用的异步原语,在许多情况下可以替代更昂贵的通道。
AsyncCell<T>
的行为类似于一个你可以等待的Cell<Option<T>>
。
这用于从回调中创建futures
use async_cell::sync::AsyncCell;
let cell = AsyncCell::shared();
let future = cell.take_shared();
thread::spawn(move || cell.set("Hello, World!"));
println!("{}", future.await);
你还可以使用async_cell进行静态变量的初始化,在阻塞行为不可接受的地方,比如OnceCell
。
use async_cell::sync::AsyncCell;
// AsyncCell::new() is const!
static GREETING: AsyncCell<String> = AsyncCell::new();
// Read the file on a background thread,
// setting a placeholder value if the thread panics.
thread::spawn(|| {
let greeting = GREETING.guard("ERROR".to_string());
let hello = std::fs::read_to_string("tests/hello.txt").unwrap();
greeting.set(hello);
});
// Do some work while waiting for the file.
// And greet the user!
println!("{}", &GREETING.get().await);
异步cell还可以用来响应变量的最新值,因为同一个cell可以重复使用多次。这是AsyncCell
与单次通道不同的一种方式
use async_cell::sync::AsyncCell;
// Allocate space for our timer.
let timer = AsyncCell::<i32>::shared();
// Try to print out the time as fast as it updates.
// Some ticks will be skipped if this loop runs too slowly!
let watcher = timer.take_weak();
spawn(async move {
while let Some(time) = (&watcher).await {
println!("Launch in T-{} ticks!", time);
}
});
// Begin counting down!
for i in (0..60).rev() {
timer.set(i);
}
尽管这个crate包含了许多实用函数,但你通常只需要 AsyncCell::new
、AsyncCell::set
和 AsyncCell::take
。
限制
Cells不是通道!通道会排队所有发送的值,直到接收者可以处理它们。cell的读取者将始终看到最近写入的值。例如,想象一个带有文本框的GUI。一个AsyncCell
非常适合观察框中的文本内容,因为不需要在每次按键时发送整个内容。但按键本身必须通过通道发送到框中,以避免任何丢失。
还避免在高争用的情况下使用AsyncCell
。在克隆值、分配异步回调等操作时,cell会暂时阻塞。一般来说,尝试从一条线程或任务填充cell,从另一条线程或任务中清空。 尽管多个futures可以等待同一个cell,但这不是高度优化的情况。
依赖项
~0–6MB
~18K SLoC