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...