怎樣理解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 { ... }` 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中的Pin問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。