1 个不稳定版本
0.1.0 | 2020 年 11 月 9 日 |
---|
#693 in 并发
23KB
213 代码行
lazy_id
提供 lazy_id::Id
,这是一个线程安全的 64 位 ID,仅在您使用它时才将其初始化到特定值,而不是在创建时。它与 no_std
(也不需要 liballoc
) 一起工作,完全无锁,目前支持 1.34.0 以上的版本,并且除了 libcore 之外没有其他依赖项。
用法
use lazy_id::Id;
struct Thing {
id: Id,
// other fields, ...
}
// Now this function can be const, allowing use in statics
const fn new_thing() -> Thing {
Thing { id: Id::lazy(), /* ... */ }
}
static C: Thing = new_thing();
// also works for non-static without meaningful overhead
let a = new_thing();
let b = new_thing();
// `Id` implements `PartialEq`, and many other useful traits.
assert!(a.id != b.id && a.id != C.id);
这有什么好处吗?
如果您需要为您的类型提供一个唯一的实例 Id
,通常的方法是在每次分配 ID 时递增全局原子。
这里唯一的问题是,如果您想将您的类型存储在某种类型的 static
中,您需要使用 OnceCell
、lazy_static
或其他懒加载初始化 crate。这些 crate 没问题,并且不太可能引起性能问题的大部分时间,但如果没有这些,它们可能会令人沮丧,并且强迫用户使用您的库可能会非常不理想。
如果您之前是 no_std
— 您本质上需要在执行泛型线程安全懒初始化时持有锁,而在无 std 中这样做需要自旋锁,这并不理想(这也是为什么 once_cell
需要 std 才能提供 sync
功能的原因)。
那么,为什么 lazy_id
没有这个问题呢?好吧,我们不做任何类型的泛型初始化。我们的初始化非常具体和具体,并且旨在避免锁定。这意味着我们可以轻松地避免无 std 中的任何自旋,而无需任何自旋。