#pin #owned #move #rvalue

nightly no-std owned-pin

内存中既拥有又固定数据的包装器

10个版本 (稳定版)

1.3.3 2023年12月2日
1.3.1 2023年12月1日
1.2.0 2023年11月30日
0.2.0 2023年11月30日
0.1.1 2023年11月30日

#272 in 内存管理

MIT/Apache

66KB
1K SLoC

Owned Pin

Cargo Documentation License

此crate处理由某些实体拥有的数据,但(可能)在内存中不可移动。它受到C++中R值引用的启发。

更多信息请参阅文档

示例

仅使用Pin<P>,我们无法保证值的移动语义。

use core::pin::{Pin, pin};
use core::marker::PhantomPinned;

fn try_to_take_the_ownership_of<T>(pinned: Pin<&mut T>) {}

let mut value = pin!(PhantomPinned);
// The caller can reborrow the value...
try_to_take_the_ownership_of(value.as_mut());
// ... so the same pinned data can be used twice,
// thus unable to guarantee the move semantics.
try_to_take_the_ownership_of(value.as_mut());

实际上,这是因为没有这样的智能指针通过持有栈上某个位置的唯一引用来拥有数据。

因此,我们引入了智能指针OnStack<T>和别名OPin<T> = Pin<OnStack<T>>,这两个都“拥有”和“固定”栈上的数据,使得上面的示例能够按预期工作

use owned_pin::{OPin, opin};
use core::marker::PhantomPinned;

fn take_the_ownership_of<T>(owned_and_pinned: OPin<T>) {}

let value = opin!(PhantomPinned);
// The `as_mut` method of `OPin` actually
// returns a `Pin<&mut T>`...
take_the_ownership_of(value);
// ... so the value itself cannot be used again.
// The line below causes rustc to emit `E0382`.
// take_the_ownership_of(value);

对于实现了Unpin的数据,我们甚至可以从包装器安全且稳定地将其移动出来

use owned_pin::{opin, unpin};

// Pins the value onto the stack.
let pinned = opin!(String::from("Hello!"));
// Retrieves back the data because `String` is `Unpin`.
let string: String = unpin(pinned);

许可证

MIT OR Apache-2.0

依赖项

~0.4–0.9MB
~19K SLoC