Pin
是一个结构 struct,Unpin
是一个特征 trait。Pin
唯一的结构体成员就是一个指针(例如引用和Box
)。它能保证这个指针指向的数据不被移动。Unpin
代表数据可以被安全地移动,!Unpin
代表数据不可以被安全移动。通常!Unpin
的都是自引用类型。- 如果一个
Unpin
类型的指针被放入Pin
中,实际上没有任何意义,因为Unpin
类型本身就是可以被安全地移动的。此时,Pin
也不会保证指向的数据不被移动。因此,Pin<&mut u8>
和&mut u8
几乎没有区别。
如果要使Pin
保证数据不会被移动的特性生效,那么存放的数据必须是!Unpin
类型的指针。 - 可以通过引入一个
std::marker::PhantomPinned
成员来为结构体实现!Unpin
。原理是,这个标记类型本身是!Unpin
的。一旦结构体包含了!Unpin
成员,那么整个结构体就会是!Unpin
。 - async 函数返回的 Future 默认就是
!Unpin
的,但是很多时候我们需要一个Unpin
的 Future。解决方法是将 Future 通过<Box>
固定到堆上,就能是Unpin
了,再通过Pin
保证其不被移动,即最终获取一个Pin<Box<Future>>
。
例如常见的约束可能是:
fn execute_unpin_future(x: impl Future
那么
Pin<Box<Fut>>
即满足了impl Future
,又能实现Unpin
. - 也可以
Pin
到栈上,但是需要用到 unsafe。函数返回时栈帧会释放,而且 rust 编译优化可能会在栈帧内移动数据。因此,一般不要这么做。
暂无评论