新提出的Pin类型有哪些用例?

时间:2018-04-19 06:07:50

标签: reference rust

不稳定的Rust中有一个新的Pin类型,RFC已经合并。据说传递引用时它被称为游戏改变者,但我不确定应该如何以及何时应该使用它。

任何人都可以用外行的方式解释它吗?

2 个答案:

答案 0 :(得分:9)

什么是钉扎?

在编程中,固定X意味着指示X不要移动。

例如:

  • 将线程固定到CPU内核,以确保它始终在同一个CPU上执行,
  • 将对象固定在内存中,以防止垃圾收集器移动它(in C# for example)。

Pin类型是什么?

Pin类型的目的是将对象固定在内存中。

它允许获取对象的地址,并保证只要Pin的实例存活,该地址将保持有效。

有什么用例?

开发它的主要用例是支持 Generators

生成器的想法是使用yield编写一个简单的函数,并让编译器自动将此函数转换为状态机。生成器所携带的状态是需要从一次调用保存到另一次调用的“堆栈”变量。

Pin旨在修复的生成器的关键难点在于,生成器可能最终存储对其自己的数据成员之一的引用(毕竟,您可以创建对堆栈值的引用)或引用最终由其自己的数据成员拥有的对象(例如,从&T获得的Box<T>)。

这是自引用结构的子结构,直到现在需要自定义库(以及许多unsafe)。自引用结构的问题是,如果结构移动,它包含的引用仍然指向内存。

Pin显然已经解决了这个多年前的Rust问题。作为图书馆类型。它创建了额外的保证,只要存在Pin,就无法移动固定值。

因此,用法是首先创建所需的结构,随意返回/移动它,然后当你对它在内存中的位置感到满意时初始化固定的引用。

答案 1 :(得分:3)

Pin类型的一种可能用途是自引用对象; an article by ralfj提供了SelfReferential结构which would be very complicated without it的示例:

#![feature(pin, arbitrary_self_types, optin_builtin_traits)]

use std::ptr;
use std::mem::Pin;
use std::boxed::PinBox;
use std::marker::Unpin;

struct SelfReferential {
    data: i32,
    self_ref: *const i32,
}

impl !Unpin for SelfReferential {}

impl SelfReferential {
    fn new() -> SelfReferential {
        SelfReferential { data: 42, self_ref: ptr::null()  }
    }

    fn init(mut self: Pin<SelfReferential>) {
        let this : &mut SelfReferential = unsafe { Pin::get_mut(&mut self) };
        // Set up self_ref to point to this.data.
        this.self_ref = &mut this.data as *const i32;
    }

    fn read_ref(mut self: Pin<SelfReferential>) -> Option<i32> {
        let this : &mut SelfReferential = unsafe { Pin::get_mut(&mut self) };
        // Dereference self_ref if it is non-NULL.
        if this.self_ref == ptr::null() {
            None
        } else {
            Some(unsafe { *this.self_ref })
        }
    }
}

fn main() {
    let mut s = PinBox::new(SelfReferential::new());
    s.as_pin().init();
    println!("{:?}", s.as_pin().read_ref()); // prints Some(42)
}