您好,登錄后才能下訂單哦!
怎樣理解Rust中的Pin,針對這個(gè)問題,這篇文章詳細(xì)介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡單易行的方法。
相關(guān)概念
Pin<P<T>>
&mut T
。
Pin<P>
定義如下:pub struct Pin<P> { pointer: P,}
std::marker
中,如果一個(gè)
T: Unpin
,就說明T在pin后可以安全的移動(dòng),實(shí)際就是可以拿到&mut T
。
pub auto trait Unpin {}
pub struct PhantomPinned;
#[stable(feature = "pin", since = "1.33.0")]
impl !Unpin for PhantomPinned {}
Pin<P>
的實(shí)現(xiàn)impl<P: Deref<Target: Unpin>> Pin<P> { pub fn new(pointer: P) -> Pin<P> { unsafe { Pin::new_unchecked(pointer) } }}
T: Unpin
,才可以new出一個(gè)
Pin<P<T>>
。這里的T就是應(yīng)該被pin的實(shí)例,可是由于
T: Unpin
實(shí)際上T的實(shí)例并不會(huì)被pin。也就是說,T沒有實(shí)現(xiàn)Unpin trait時(shí),T才會(huì)被真正的pin住。Pin::new
方法要求
T: Unpin
,通常創(chuàng)建一個(gè)不支持Unpin的T的pin實(shí)例的方法是用
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
,所以就不能移動(dòng)Node實(shí)例。注意,這里是不能移動(dòng)Node實(shí)例,node_pined是Pin實(shí)例,是可以移動(dòng)的。mut Node
,也可以移動(dòng)Node實(shí)例,但這些unsafe的操作就需要程序員自己去承擔(dān)風(fēng)險(xiǎn)。Pin相關(guān)方法中對此有很詳細(xì)的說明。Box<T>
或&mut T
)的結(jié)構(gòu),在T: Unpin
的情況下,Pin<Box<T>>
和Box<T>
是類似的,通過DerefMut
就可以直接得到&mut T
,在T沒有實(shí)現(xiàn)Unpin的情況下,Pin<Box<T>>
只能通過Deref
得到&T
,就是說T被pin住了。
std::mem::swap
方法,也可以是
Option::take
方法,還可能是
Vec::set_len
、
Vec::resize
方法等,這些可都是safe等方法。這些方法的共同點(diǎn)都是需要
&mut Self
,所以說只要不暴露
&mut Self
,就可以達(dá)到pin的目標(biāo)。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
方法的第一個(gè)參數(shù)是
Pin<&mut Self>
,如果在
Future::poll
方法中有類似
std::mem::swap
等方法調(diào)用,就有可能導(dǎo)致AsyncFuture被移動(dòng),那么AsyncFuture中的自引用field就會(huì)導(dǎo)致災(zāi)難。Future::poll
代碼是自動(dòng)生成的,可以不調(diào)用
std::mem::swap
等方法,就不會(huì)導(dǎo)致AsyncFuture被移動(dòng)。的確是這樣的,如果在這里將
Future::poll
的第一個(gè)參數(shù)改為
Box<Self>
或者
&mut Self
,大概率是沒有問題的。很多executor的實(shí)現(xiàn),都是要求Future是支持Unpin,因?yàn)樵趐oll代碼中的確有修改Self的需求,但不會(huì)產(chǎn)生錯(cuò)誤,也是這個(gè)原因。&mut Self
,如下:pub trait Future { type Item; type Error; fn poll(&mut self) -> Poll<Self::Item, Self::Error>;}
&mut Self
。Future::poll
方法參數(shù)的需要。Future::poll
方法之外,不建議使用Pin,也沒有必要使用Pin.關(guān)于怎樣理解Rust中的Pin問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。