1 个不稳定版本
0.1.0 | 2024年6月23日 |
---|
#436 在 并发
34KB
587 行
highroller
用法
此 Rust 包提供了一个静态可用的、线程安全的滚动索引。适用于 UUID 过于复杂而需要低成本替代方案的场景。
提供的主要函数是 rolling_idx()
。简单来说
let id1 = highroller::rolling_idx();
let id2 = highroller::rolling_idx();
println!("Id 1 is: {}", id1);
println!("Id 2 is: {}", id2);
// outputs:
// Id 1 is: 0
// Id 2 is: 1
函数 rolling_idx()
返回当前索引值。检索后,索引值增加 1。这样,每次调用此函数时,您都会得到一个唯一、不断增长的滚动索引。
请注意,滚动索引是运行时特定的,并且每次您的应用程序启动时都会重置。
滚动索引也是线程安全的,这意味着您可以从多个线程同时访问它,而不会遇到与并发数据访问相关的问题。
*待更多稳健的测试,应该成立。
特性标志
highroller
提供了几个特性标志以提高灵活性。
特性标志 | 默认 | 描述 |
---|---|---|
strict |
启用 | 在溢出时引发恐慌并禁用 RUID - 数字类型比较和算术。 (当禁用时,溢出将回绕) |
ruid_type |
禁用 | 启用滚动唯一 ID (RUID ) 类型,它是对滚动索引的包装 |
allow_arithmetics |
禁用 | 可选支持对 RUID 执行算术运算 (请注意,如果不启用 strict ,您应该知道自己在做什么,因为它可能导致模糊的行为) |
size (单独的标志) | u16_index |
选择滚动索引的大小:u8_index 、u16_index 、u32_index 、u64_index 、u128_index 、usize_index |
如果您需要特定的滚动索引大小,或者您想使用 RUID
实现更明确的类型,请根据您的用例启用相应的特性。strict
特性可以帮助您捕获溢出,而 allow_arithmetics
标志扩展了 RUID
的功能,以支持算术运算。
RUID
“滚动唯一标识符”(RUID)本质上是对滚动索引的包装,支持可选的算术运算,以及完整的等价关系方法和显示方法。您可以使用 ruid_type
功能标志来启用 RUID
并将其用于您的程序。有关 RUID
的更多信息,请参阅“附加信息”部分。
示例
考虑一个基本游戏,其中您召唤数字战士。每个召唤的战士都需要有一个唯一的标识符。为每个战士创建复杂的 UUID 可能会消耗宝贵的资源,并导致游戏性能问题。
这就是您可以利用 highroller
来分配唯一标识符的地方。它简单且高效
use std::sync::{Arc, Mutex};
use std::thread;
use rand::Rng;
struct Fighter {
id: u8,
power: u32,
};
// create a register for fighters
let fighters_register = Arc::new(Mutex::new(Vec::new()));
// create four threads as four different arenas
let arenas = 4;
// first, gather a randomized set of 20 fighters (power randomized) for each arena
let mut handlers = Vec::new();
for _ in 0..arenas {
let fighters_register = Arc::clone(&fighters_register);
handlers.push(thread::spawn(move || {
let mut rng = rand::thread_rng();
let mut ids = Vec::new();
for _ in 0..20 {
let fighter = Fighter {
id: highroller::rolling_idx(),
power: rng.gen_range(1, 100),
};
ids.push(fighter.id);
fighters_register.lock().unwrap().push(fighter);
}
ids
}));
}
// do a simple tournament that reveals a champion for each arena
let mut champions: Vec<Fighter> = Vec::with_capacity(arenas);
for handler in handlers {
let arena_fighters = handler.join().unwrap();
let fighters = fighters_register.lock().unwrap();
// Find the fighter with the highest power in each arena
let champion = arena_fighters.iter()
.map(|&id| fighters.iter().find(|fighter| fighter.id == id).unwrap())
.max_by_key(|fighter| fighter.power)
.unwrap()
.clone();
champions.push(champion);
}
// now match the top against each other in a playoff that is based
// on the power we randomized earlier
let ultimate_champion = champions.into_iter()
.max_by_key(|fighter| fighter.power)
.unwrap();
// print the winner by id
println!("The ultimate champion is fighter with id: {}", ultimate_champion.id);
在这个例子中,我们创建的每个战士都从 highroller::rolling_idx()
获取一个唯一的标识符。由于滚动索引是递增的,因此每个战士都会得到一个唯一的 ID。这不需要任何复杂的 UUID 或类似的开销,并且实用。
请记住,每次应用程序重新启动时,索引都会重置。如果您需要在应用程序重启之间保持持久性,您将需要实现额外的策略。
问题
有时,您需要一个非常简单的保证唯一标识符。使用 UUID 可能过于复杂,并带来您可能不需要承担的资源成本,如果您的用例非常简单且范围不大。
这时就出现了静态滚动计数器。
概念很简单:拥有一个静态可用的滚动值,该值在每次提取后自动递增。添加一些线程安全性措施,您就拥有了一个非常易于使用且保证唯一的标识符。
主要适用于简单的标识需求,它避免了许多复杂性,并且可以非常便宜地运行。
附加信息
使用 ruid_type
功能标志,您可以将 RUID
(滚动唯一标识符)用作自定义整数类型。您可以将 RUID
转换为标准整数或反之,比较两个 RUID
,如果 allow_arithmetics
标志开启,则可以使用算术运算来操作 RUID
,并且由于它们实现了 fmt::Display
特性,因此可以打印 RUID
。
RUID
的使用示例
use highroller::RUID;
let id1 = RUID::new();
let id2 = RUID::new();
assert_ne!(id1, id2);
支持
无论您是否使用此项目、从中学习到知识还是只是喜欢它,请考虑通过购买我一杯咖啡来支持它,这样我就可以投入更多时间从事此类开源项目:)
许可协议
您可以在 此处 查看完整的许可协议
本项目根据 MIT 许可协议授权。
依赖项
~10KB