rust的綠卡 rust中的Pin詳解

2021-10-13 07:56:14 字數 2018 閱讀 3067

rust中的pin詳解

相關概念

pin這是乙個struct,作用就是將p所指向的t在記憶體中固定住,不能移動。說白一些,就是不能通過safe**拿到&mut t。

pin定義如下:

pub struct pin

pointer: p,

unpin

這是乙個trait,定義在std::marker中,如果乙個t: unpin,就說明t在pin後可以安全的移動,實際就是可以拿到&mut t。

pub auto trait unpin {}

!unpin

對unpin取反,!unpin的雙重否定就是pin。如果乙個型別中包含了phantompinned,那麼這個型別就是!unpin。

pub struct phantompinned;

#[stable(feature = "pin", since = "1.33.0")]

impl !unpin for phantompinned {}

pin的實現

我們這裡只關注safe方法,重點是new方法:

impl> pin

pub fn new(pointer: p) -> pin

unsafe

可以看出,只有p所指向的t: unpin,才可以new出乙個pin

>。這裡的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> ` 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, cx: &mut context) -> poll {

注意future::poll方法的第乙個引數是pin,如果在future::poll方法中有類似std::mem::swap等方法呼叫,就有可能導致asyncfuture被移動,那麼asyncfuture中的自引用field就會導致災難。

可能你也注意到了,這裡的future::poll**是自動生成的,可以不呼叫std::mem::swap等方法,就不會導致asyncfuture被移動。的確是這樣的,如果在這裡將future::poll的第乙個引數改為box或者&mut self,大概率是沒有問題的。很多executor的實現,都是要求future是支援unpin,因為在poll**中的確有修改self的需求,但不會產生錯誤,也是這個原因。

但是,對於程式設計師實現future的情況,問題就來了。**如果poll的引數是&mut self,那麼程式設計師就可能使用safe**(比如std::mem::swap)產生錯誤,這是與rust安全編碼的理念相衝突的。**這就是pin引入的根本原因!

其實,在future 0.1版本中,poll的這個引數就是&mut self,如下:

pub trait future {

type item;

type error;

fn poll(&mut self) -> poll<:item self::error>;

總結一下

pin實際是對p指標的限制,在t沒有實現unpin的情況下,避免p指標暴露&mut self。

pin的引入是async/.await非同步程式設計的需要,核心就是future::poll方法引數的需要。

除了future::poll方法之外,不建議使用pin,也沒有必要使用pin.

rust中的型別

rust提供了幾種機制來實現基本型別和使用者自定義型別的轉換和定義。rust中沒有提供基本型別之間隱式地型別的轉換。但是,我們可以通過as關鍵字來進行顯示型別的轉換。在rust中,數字型別的轉換和c語言中的轉換一樣,除了c語言中的未定義的行為。整數型別之間的所有轉換情況都已經在rust中定義好了。禁...

Rust中的常量

示例程式 fn main max points 上述程式定義了乙個常量 max points 並賦值為 100000。rust 中使用 const 關鍵字來宣告常量 constant 必須顯式地標註常量值得型別。常量和變數的區別 常量可以被宣告在任何作用域中,甚至包括全域性作用域。這在乙個值需要被不...

Rust中巨集的理解

巨集相比函式是相對難以理解的,更加難以掌握,編寫理解以及除錯都很有困難。但它的存在肯定是有它比較獨特的地方的。相比函式,巨集是用來生成 的,在呼叫巨集的地方,編譯器會先將巨集進行展開,生成 然後再編譯展開後的 在rust中,函式是不接受任意多個引數的,巨集可以辦到。巨集定義格式macro rules...