首页 > 数据库 > 数据库开发技术 > Rust中的Pin详解
相关概念
Pin<P<T>>&mut T。Pin<P>定义如下:pub struct Pin<P> {pointer: P,}
std::marker中,如果一个T: Unpin,就说明T在pin后可以安全的移动,实际就是可以拿到&mut T。pub auto trait Unpin {}
pub struct PhantomPinned;#[stable(feature = "pin", since = "1.33.0")]impl !Unpin for PhantomPinned {}
Pin<P>的实现impl<P: Deref<Target: UnpinPin<P> {pub fn new(pointer: P) -> Pin<P> {unsafe { Pin::new_unchecked(pointer) }}}
T: Unpin,才可以new出一个Pin<P<T>>。这里的T就是应该被pin的实例,可是由于T: Unpin实际上T的实例并不会被pin。也就是说,T没有实现Unpin trait时,T才会被真正的pin住。Pin::new方法要求T: Unpin,通常创建一个不支持Unpin的T的pin实例的方法是用Box::pin方法,定义如下:pub fn pin(x: T) -> Pin<Box<T>> {(box x).into()}
let node_pined: Pin<Box<Node= Box::pin(Node::new());let movded_node_pined = node_pined;
&mut Node,所以就不能移动Node实例。注意,这里是不能移动Node实例,node_pined是Pin实例,是可以移动的。mut Node,也可以移动Node实例,但这些unsafe的操作就需要程序员自己去承担风险。Pin相关方法中对此有很详细的说明。Box<T>或&mut T)的结构,在T: Unpin的情况下,Pin<Box<T>>和Box<T>是类似的,通过DerefMut就可以直接得到&mut T,在T没有实现Unpin的情况下,Pin<Box<T>>只能通过Deref得到&T,就是说T被pin住了。std::mem::swap方法,也可以是Option::take方法,还可能是Vec::set_len、Vec::resize方法等,这些可都是safe等方法。这些方法的共同点都是需要&mut Self,所以说只要不暴露&mut Self,就可以达到pin的目标。let fut_one = /* ... */;let fut_two = /* ... */;async move {...fut_one.await;...fut_two.await;...}
The `Future` type generated by our `async { ... }` blockstruct AsyncFuture {...fut_one: FutOne,fut_two: FutTwo,state: State,}List of states our `async` block can be inenum State {AwaitingFutOne,AwaitingFutTwo,Done,}impl Future for AsyncFuture {type Output = ();fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {...}}
Future::poll方法的第一个参数是Pin<&mut Self>,如果在Future::poll方法中有类似std::mem::swap等方法调用,就有可能导致AsyncFuture被移动,那么AsyncFuture中的自引用field就会导致灾难。Future::poll代码是自动生成的,可以不调用std::mem::swap等方法,就不会导致AsyncFuture被移动。的确是这样的,如果在这里将Future::poll的第一个参数改为Box<Self>或者&mut Self,大概率是没有问题的。很多executor的实现,都是要求Future是支持Unpin,因为在poll代码中的确有修改Self的需求,但不会产生错误,也是这个原因。&mut Self,如下:pub trait Future {type Item;type Error;fn poll(&mut self) -> Poll<Self::Item, Self::Error>;}
&mut Self。Future::poll方法参数的需要。Future::poll方法之外,不建议使用Pin,也没有必要使用Pin.原文作者:Rust语言中文社区;如有侵权,请联系管理员删除。