我正在阅读The Rustonomicon,并遇到了section on poisoning。一个类型中毒的书面例子是当一个“ Mutex会在恐慌期间丢弃其中一个MutexGuards(它在获得锁定时返回的东西)时会自行中毒。”(Rustonomicon,第7.2节,第3段)
我很不自然,但突然很好奇。
为了找到类型中毒的实施演示,谷歌搜索“如何毒害一种类型”会产生无用的结果,从化学毒物类型列表到口袋妖怪。 “类型中毒的代码示例”的结果大致相同。
是否有人可以使用代码段演示类型中毒?我不在乎示例是否在Rust中,但也许这很重要......因为在某些语言中只能以某种方式中毒?
我发现中毒发生在其他语言中,或至少C++ function poisoning和namespace poisoning。 (搜索“Java类型中毒”会因检测java bean poisoned dogs到how to poison mobs in Minecraft而产生无用但有趣的结果。)
然而,这些示例缺少代码中的示例链接。我希望看到它在行动。
答案 0 :(得分:4)
通过检查Drop
实施中std::thread::panicking
的返回值来实现中毒。如果它返回true
,则该值应该中毒。这是一个例子:
use std::cell::Cell;
use std::panic::{self, AssertUnwindSafe};
use std::thread;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum ResourceState {
Available,
Locked,
Poisoned,
}
struct Resource {
state: Cell<ResourceState>,
}
struct ResourceGuard<'a> {
resource: &'a Resource,
}
impl Resource {
fn new() -> Resource {
Resource {
state: Cell::new(ResourceState::Available),
}
}
fn lock(&self) -> ResourceGuard {
assert_eq!(self.state.get(), ResourceState::Available);
self.state.set(ResourceState::Locked);
ResourceGuard {
resource: self,
}
}
}
impl<'a> Drop for ResourceGuard<'a> {
fn drop(&mut self) {
self.resource.state.set(
if thread::panicking() {
ResourceState::Poisoned
} else {
ResourceState::Available
});
}
}
fn main() {
let resource = Resource::new();
println!("state: {:?}", resource.state.get()); // Available
{
println!("acquiring lock");
let _guard = resource.lock();
println!("state: {:?}", resource.state.get()); // Locked
println!("dropping lock");
}
println!("state: {:?}", resource.state.get()); // Available
let _ = panic::catch_unwind(AssertUnwindSafe(|| {
println!("acquiring lock");
let _guard = resource.lock();
println!("state: {:?}", resource.state.get()); // Locked
println!("panicking!");
panic!("panicking!");
}));
println!("state: {:?}", resource.state.get()); // Poisoned
}