1个不稳定版本
0.1.0 | 2024年3月17日 |
---|
#27 in #spawn
8KB
102 行
寄生任务
寄生任务是那些不会被任何执行器调度的任务,而是直接在调用唤醒者的线程上立即派发。
这使得异步结果可以就地处理,无需在单独的线程上排队进行后续操作。这在响应延迟是一个关键问题的场合很有用,比如在高频交易应用中。
用法
只需使用 ptask::spawn
运行一个寄生任务,它将在当前线程上立即派发,直到它 await
一个尚未完成的未来,通常是从异步通道接收。
请注意,任务内部使用 Arc
进行引用计数,因为等待的异步操作必须持有保持任务活动的唤醒者。因此,发送者可以被视为正在等待接收者的任务的拥有者。请注意,如果有多个ptask持有彼此的发送者的引用,则某些发送者必须用 Weak
引用包装起来,以避免循环引用。
use futures::{channel::mpsc, StreamExt};
use std::sync::{
atomic::{AtomicUsize, Ordering},
Arc,
};
// This demo shows how it works on a single thread.
#[test]
fn demo() {
let (tx, mut rx) = mpsc::unbounded();
let result = Arc::new(AtomicUsize::new(0));
// Spawn a ptask that runs immediately until the first `await`.
// Then the `await`ed channel holds the reference to the task.
ptask::spawn({
let result = result.clone();
async move {
while let Some(i) = rx.next().await {
result.fetch_add(i, Ordering::Relaxed);
}
result.fetch_add(10, Ordering::Relaxed);
}
});
for i in 0..10 {
// Sending to the channel makes the ptask resumes running until the next `await`.
tx.unbounded_send(i).unwrap();
assert_ne!(result.load(Ordering::Relaxed), 55);
}
// Drop the sender so that the ptask breaks out of the loop.
drop(tx);
assert_eq!(result.load(Ordering::Relaxed), 55);
}
功能
此crate支持 no_std
但需要可用的 alloc
crate。
可选功能
默认情况下,此crate将所有函数标记为 #[inline(always)]
,这确保了在需要的情况下有极好的性能。但是,如果代码大小仍然是关注点,您可以通过禁用默认功能来禁用此行为,这与普通crate一样进行内联。
依赖关系
~0.4–5.5MB
~11K SLoC