Pin 与 Unpin
- std::pin::Pin
- std::maker::Unpin
- std::maker::PhontomPinned
- impl !Unpin for T
Pin [source]
Rust展开
123456789101112131415161718192021
/// A pinned pointer.
///
/// This is a wrapper around a kind of pointer which makes that pointer "pin" its
/// value in place, preventing the value referenced by that pointer from being moved
/// unless it implements [`Unpin`].
///
/// *See the [`pin` module] documentation for an explanation of pinning.*
///
/// [`pin` module]: self
//
// Note: the `Clone` derive below causes unsoundness as it's possible to implement
// `Clone` for mutable references.
// See <https://internals.rust-lang.org/t/unsoundness-in-pin/11311> for more details.
#[stable(feature = "pin", since = "1.33.0")]
#[lang = "pin"]
#[fundamental]
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct Pin<P> {
// FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to:// - deter downstream users from accessing it (which would be unsound!),// - let the `pin!` macro access it (such a macro requires using struct// literal syntax in order to benefit from lifetime extension).// Long-term, `unsafe` fields or macro hygiene are expected to offer more robust alternatives.#[unstable(feature = "unsafe_pin_internals", issue = "none")]#[doc(hidden)]pub pointer: P,
}
Pin 可以确保被任何类型的指针T指向的数据有一个固定的位置,不能被移动和释放。
需要Pin的核心诉求是,async/await 需要一个自引用的结构体(self-referential-structs), 它表示一个结构体当中的一个字段指向了当前结构的另一个字段。
Rust展开
1234
struct SelfRefer {
val: String,
pointer_to_val: *mut String
}
这个结构体中,如果val指向的String被移动,则pointer_to_val将变成非法地址, 会引发内存安全问题。而Pin的出现就是为了避免这种场景的出现,从而保证内存安全。
对于Future
Rust展开
1234567
let f1 = /** ... */ //Future1
let f2 = /** ... */ //Future2
async move{
f1.await;
f2.await;
}
在rust底层会将上述代码编译成一个匿名结构体
Rust展开
123456789101112131415161718192021222324252627282930
struct AsyncFuture {
f1: Future1,
f2: Future2,
state: State
}
enum State {
AwaitF1.
AwaitF2,
Done
}
impl Future for AsyncFuture {
type Output = ()
fn poll(mut self: Pin<&mut Self>, context: &mut Context<'_>)-> Poll<()> {
loop {
match self.state {
State::AwaitF1 => match self.state.f1.poll() {
Poll::Ready(()) => self.state = State::AwaitF2,
Poll::Penging => return Poll::Penging
},
State::AwaitF2 => match self.state.f2.poll() {
Poll::Ready(()) => self.state = State::Done,
Poll::Penging => return Poll::Penging
},
State::Done => return Poll::Ready(())
}
}
}
}