在async中,Pinning 确保对象不会被move, 这个如何理解?
let fut_one = ...;
let fut_two = ...;
async move {
fut_one.await;
fut_two.await;
}
实际上这会生成一个匿名struct, AsyncFuture
struct AsyncFuture {
fut_one: FutOne,
fut_two: FutTwo,
state: State,
}
// List of states our `async` block can be in
enum State {
AwaitingFutOne,
AwaitingFutTwo,
Done,
}
impl Future for AsyncFuture {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
loop {
match self.state {
State::AwaitingFutOne => match self.fut_one.poll(..) {
Poll::Ready(()) => self.state = State::AwaitingFutTwo,
Poll::Pending => return Poll::Pending,
}
State::AwaitingFutTwo => match self.fut_two.poll(..) {
Poll::Ready(()) => self.state = State::Done,
Poll::Pending => return Poll::Pending,
}
State::Done => return Poll::Ready(()),
}
}
}
}
当poll第一次执行,会先poll fut_one, 如果fut_one没有完成, poll将立即返回,假如在async block中, 用了引用会如何?
async {
let mut x = [0; 128];
let read_into_buf_fut = read_into_buf(&mut x);
read_into_buf_fut.await;
println!("{:?}", x);
}
struct ReadIntoBuf<'a> {
buf: &'a mut [u8], // points to `x` below
}
struct AsyncFuture {
x: [u8; 128],
read_into_buf_fut: ReadIntoBuf<'what_lifetime?>,
}
ReadIntoBuf future 持有x这个字段的引用,但是如果AsyncFuture被move了,那么x也会被move,因为此时AsyncFuture是x的owner,这时read_into_buf_fut 中所持有的引用将被invalidating. 所以要将Future pin住,不让他move