在 Rust 中使用 futures 时,为了确保引用稳定性,可以使用 Box::pin 或 pin_mut 封装需要保持稳定的 future。但是,如果我们需要在 futures::select 宏之外使用封装后的 future,就会遇到引用稳定性问题。
为了解决这个问题,可以将封装后的 future 引用转换为不稳定的可变引用,然后在需要使用时重新封装为稳定的引用。
下面是一个示例代码:
use futures::future::FutureExt;
use futures::pin_mut;
async fn foo(input: String) -> String {
// some async operations
input
}
async fn bar(input: String) -> String {
// some async operations
input
}
#[tokio::main]
async fn main() {
let mut fut1 = foo("hello".to_string()).boxed();
let mut fut2 = bar("world".to_string()).boxed();
pin_mut!(fut1, fut2);
loop {
futures::select_biased! {
res1 = fut1 => {
let input = res1.unwrap();
fut1.as_mut().set(foo(input)).unwrap();
println!("fut1 finished with {}", input);
}
res2 = fut2 => {
let input = res2.unwrap();
fut2.as_mut().set(bar(input)).unwrap();
println!("fut2 finished with {}", input);
}
complete => break,
}
}
}
在这个示例中,我们使用了 futures::select_biased 宏来轮流执行两个 future fut1 和 fut2 的逻辑。通过使用 pin_mut! 宏来转换可变引用到 Boxed Future,我们可以保持引用的稳定性。
在 select 宏执行每个 future 之前,我们使用 as_mut() 函数将 future 的引用转换为可变引用,并在执行完成后重新封装为稳定的 Boxed Future 对象。
这种方式可以确保 future 的引用在不同的执行过程中保持稳定,同时又不会影响 select 宏的正确执行。