我正试图从par_iter()
内部捕捉恐慌,并继续执行par_iter
封锁后的工作。
如果我有这个,我会正确地获得一切,而不会出现恐慌:
let dog: Dog = Dog {
name: "Dog",
vector: vec![1, 2, 3, 4, 5],
};
let cat: Cat = Cat {
name: "Cat",
vector: vec![1, 2, 3],
};
let pig: Pig = Pig {
name: "Pig",
vector: vec![1, 2, 3, 4, 5],
};
let mut v: Vec<Box<dyn Animal>> = Vec::new();
v.push(Box::new(cat));
v.push(Box::new(dog));
v.push(Box::new(pig));
let total = v
.par_iter()
.map(|x| {
println!("{} vector[1] is {:?}", &x.name(), &x.vector()[1]);
x.vector()[1].clone()
})
.collect::<Vec<(i32)>>();
let sum: i32 = total.iter().sum();
println!("sum: {}", sum);
我在par_iter
之后得到总和
Cat vector[1] is 2
Dog vector[1] is 2
Pig vector[1] is 2
sum: 6
当我尝试访问超出向量长度的索引时,我仍然会打印出包括恐慌在内的所有内容,但不要进入sum
:
let total = v
.par_iter()
.map(|x| {
println!("{} vector[4] is {:?}", &x.name(), &x.vector()[4]);
x.vector()[4].clone()
})
.collect::<Vec<(i32)>>();
let sum: i32 = total.iter().sum();
println!("sum: {}", sum);
结果:
Running `target/debug/playground`
thread '<unnamed>' panicked at 'index out of bounds: the len is 3 but the index is 4', /rustc/4560ea788cb760f0a34127156c78e2552949f734/src/libcore/slice/mod.rs:2717:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
Standard Output
Dog vector[4] is 5
Pig vector[4] is 5
我尝试检查如果实施panic_handler
可以做什么:
let panic_handler = move |err: Box<dyn Any + Send>| {
println!("hello");
};
rayon::ThreadPoolBuilder::new()
.num_threads(2)
.panic_handler(panic_handler)
.build_global()
.unwrap();
它不起作用,甚至没有被使用:
warning: unused variable: `err`
--> src/main.rs:52:31
|
52 | let panic_handler = move |err: Box<dyn Any + Send>| {
| ^^^ help: consider prefixing with an underscore: `_err`
我真正的问题不在于超越向量的界限,而是关于par_iter
中的恐慌,如果我不知道它是否会恐慌。我的目标是收集结果并继续处理不会引起恐慌的内容。
答案 0 :(得分:1)
尝试使用get
(如果索引4处有元素,则返回Some(element)
,None
则返回):
let total = v.par_iter().map(|x| {
println!("{} vector[4] is {:?}", &x.name(), &x.vector().get(4));
x.vector().get(4).map(|x| x.clone())
}).collect::<Vec<Option<i32>>>();
然后,total
将包含存在相应元素的Some(n)
,否则将包含None
。
答案 1 :(得分:1)
我的问题是使用::std::panic::catch_unwind()
的{{3}}:
use ::rayon::prelude::*;
trait Animal: Sync + Send {
fn vector(self: &'_ Self) -> Vec<i32>;
fn name(self: &'_ Self) -> String;
}
struct Cat {
name: &'static str,
vector: Vec<i32>,
}
impl Animal for Cat {
fn vector(self: &'_ Self) -> Vec<i32> {
self.vector.clone()
}
fn name(self: &'_ Self) -> String {
self.name.to_string()
}
}
struct Dog {
name: &'static str,
vector: Vec<i32>,
}
impl Animal for Dog {
fn vector(self: &'_ Self) -> Vec<i32> {
self.vector.clone()
}
fn name(self: &'_ Self) -> String {
self.name.to_string()
}
}
struct Pig {
name: &'static str,
vector: Vec<i32>,
}
impl Animal for Pig {
fn vector(self: &'_ Self) -> Vec<i32> {
self.vector.clone()
}
fn name(self: &'_ Self) -> String {
self.name.to_string()
}
}
fn main() {
::rayon::ThreadPoolBuilder::new()
.num_threads(2)
// .panic_handler(move |_: Box<dyn Any + Send>| println!("hello"))
.build_global()
.unwrap();
match ::std::panic::catch_unwind(move || {
let dog: Dog = Dog {
name: "Dog",
vector: vec![1, 2, 3, 4, 5],
};
let cat: Cat = Cat {
name: "Cat",
vector: vec![1, 2, 3],
};
let pig: Pig = Pig {
name: "Pig",
vector: vec![1, 2, 3, 4, 5],
};
let v: Vec<Box<dyn Animal>> = vec![Box::new(cat), Box::new(dog), Box::new(pig)];
let total = v
.par_iter()
.map(|x| {
let vector_4 = x.vector()[4].clone();
println!("{} vector[4] is {:?}", &x.name(), vector_4);
vector_4
})
.collect::<Vec<(i32)>>();
let sum: i32 = total.iter().sum();
println!("sum: {}", sum);
}) {
Ok(()) => (),
Err(err) => {
let err_msg = match (err.downcast_ref(), err.downcast_ref::<String>()) {
(Some(&s), _) => s,
(_, Some(s)) => &**s,
_ => "<No panic message>",
};
eprintln!("Rayon panicked: {}", err_msg);
}
}
println!("This code is always reached");
}