怎样理解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: Unpin>> Pin<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 { ... }` block
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<()> {
...
}
}
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中的Pin问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。