Pin & Unpin
在同步情况下,Rust 的借用机制足以保证内存引用的安全(只允许一个可变引用,可变引用与不可变引用不能存在于同一作用域中)。
在异步编程中,存在数据竞争问题,当多个任务访问和修改同一数据时,Rust 的借用规则无法静态检查异步任务之间的调度和执行顺序,因此无法提供对于数据竞争的静态保证。
Pin
防止一个类型在内存中移动。Pin
是一个结构体:
pub struct Pin<P> {
pointer: P,
}
Pin
包裹一个指针,并且能确保该指针指向的数据不会移动,例如 Pin<&mut T>
,Pin<&T>
,Pin<Box<T>>
,都能确保 T
不会被移动。
!Unpin
可以被 Pin
住的值实现的特征是 !Unpin
。使用标记类型 PhantomPinned
可以自动让编译器为结构体实现 !Unpin
特征:
struct Test {
a: String,
// 裸指针
b: *const String,
_marker: PhantomPinned,
}
Pin 这个结构体并不是让 Pin 中的值变的不可移动, 而是让你无法在不使用
unsafe
方法的前提下改动 Pin 中的地址。 真正标志一个值是不是不可移动的只有!Unpin
这个标志. 这就是 Pin 只是一个结构体, 而!Unpin
是一个编译器自动实现的 trait 的原因。
Unpin
Unpin
是一个特征,表明一个类型可以被随意移动,绝大多数类型都自动实现了 Unpin
特征。
实现 Unpin
特征的类型被 Pin
包裹后没有任何效果。