#pointers #tags

no-std tagged-pointer

平台无关的空间高效标记指针

12个版本

0.2.7 2023年4月28日
0.2.6 2022年12月20日
0.2.3 2022年9月4日
0.2.2 2022年4月28日
0.1.3 2021年3月19日

#330数据结构

每月22次下载
2 个crate中使用(通过 btree-vec

Apache-2.0

36KB
401

tagged-pointer

本crate提供了一个标记指针的实现:以空间高效的方式包含整数标记的指针。

除非使用后备实现(见下面的 假设 部分),TaggedPtrOption<TaggedPtr> 都将具有指针的大小。

本crate只依赖于 core,因此可以在 no_std 环境中使用。

示例

use core::mem::size_of;
use core::ptr::NonNull;
use tagged_pointer::TaggedPtr;

#[repr(align(4))]
struct Item(u32, u32);

// `TaggedPtr` and `Option<TaggedPtr>` are both the size of a pointer:
assert_eq!(size_of::<TaggedPtr<Item, 2>>(), size_of::<*mut ()>());
assert_eq!(size_of::<Option<TaggedPtr<Item, 2>>>(), size_of::<*mut ()>());

let item1 = Item(1, 2);
let item2 = Item(3, 4);

// We can store two bits of the tag, since `Item` has an alignment of 4.
let tp1 = TaggedPtr::<_, 2>::new(NonNull::from(&item1), 1);
let tp2 = TaggedPtr::<_, 2>::new(NonNull::from(&item2), 3);

let (ptr1, tag1) = tp1.get();
let (ptr2, tag2) = tp2.get();

assert_eq!((ptr1, tag1), (NonNull::from(&item1), 1));
assert_eq!((ptr2, tag2), (NonNull::from(&item2), 3));

假设

此crate依赖于 pointer::align_offset 在某些情况下不会失败。具体来说,当在指向 u8 的指针上以非const上下文调用 align_offset 时,如果所需的对齐小于或等于由提供的指针指向的分配的对齐,则必须成功。在实践中,即使在具有 -Zmiri-symbolic-alignment-check 标志的 Miri 中,这也是正确的,但 align_offset 的规范实际上允许实现不遵循此行为。如果您因此遇到问题,请在 Git仓库 中提交问题。作为一个替代方案,您可以启用 fallback 功能,这会以使 TaggedPtr 大小加倍为代价来避免依赖于 align_offset

请注意,此crate始终是安全的:不遵循所需行为的 align_offset 实现可能会引起panic,但不会导致未定义行为。

遗憾的是,目前在Rust中实现空间高效的标记指针没有一种不做出一些假设的方法。然而,这种方法与通常的方法(将指针转换为 usize 并重用低位)相比有一些优点:通常的方法对平台特定的指针表示做出了假设(目前适用于所有由rustc支持的平台,但如果有新架构的支持可能会被否定,并且确实存在不允许重用对齐指针低位位的真实架构),而此crate的假设是平台无关的(除了Rust已施加的要求,如8位字节)并且被所有已知的Rust实现所满足,包括带有 -Zmiri-symbolic-alignment-check 的Miri。

依赖关系

~0–8MB
~57K SLoC