我想在限定了作用域的线程池上下文中,使用scoped_thread_pool跨线程共享(和更改)mutable Vec
。
let ids_for_discard: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(Vec::new()));
let scoped_outcome = self.threadpool.scoped(|scope| {
// here I iterate through a Vec of objects...
for text_doc_hit_obj in &self.handling_framework.text_doc_hit_objs_for_processing {
// each thread will need its Arc clone...
let ids_for_discard = Arc::clone(&ids_for_discard);
scope.execute(move || {
// this (above) closure MUST return "()"... so
// I use an inner closure to capture errors efficiently, using the "?" operator several times
let inner_closure = move || -> Result<(), Box<dyn std::error::Error>> {
...
let id_string = text_doc_hit_obj._id.clone();
// let _ = ids_for_discard.lock()?.push(id_string); // fails to compile
let _ = ids_for_discard.lock().unwrap().push(id_string); // passes
字符串
.如果我使用match
子句,它也会通过。
我使用上面的?
运算符得到的错误是:
error[E0515]: cannot return value referencing local data `ids_for_discard`
--> src\indexing_pool.rs:112:19
|
112 | ... let _ = ids_for_discard.lock()?.push(id_string);
| ----------------------^
| |
| returns a value referencing data owned by the current function
| `ids_for_discard` is borrowed here
型
有人能解释一下为什么?
在这里编译失败吗?我真的很难理解。我想知道是否有一个危险,即尝试push
和Err
.
NB这也失败了:
let id_string = text_doc_hit_obj._id.clone();
let mut vec = ids_for_discard.lock()?;
vec.push(id_string);
型
产品编号:error[E0515]: cannot return value referencing local data 'ids_for_discard'
同样,如果将?
替换为unwrap()
,则通过。
我看到Mutex::lock()
的签名是pub fn lock(&self) -> LockResult<MutexGuard<'_, T>>
...而LockResult
是pub type LockResult<Guard> = Result<Guard, PoisonError<Guard>>;
,难道Box<dyn std::error::Error>>
无法捕捉到这种错误?
2条答案
按热度按时间33qvvth11#
PoisonError
确实包含一个MutexGuard
和一个对Arc<Mutex<..>>
的引用,在你的例子中,Arc<Mutex<..>>
是函数的局部变量,所以你不能返回对它的引用。你可以map_err
来交换错误,它不包含对任何局部变量的引用:字符串
rryofs0p2#
Mutex::lock返回一个LockResult,根据它的文档:
请注意,Err变量还携带了相关的保护,并且可以通过into_inner方法获取。
我不太确定在什么情况下使用锁是明智的,即使它中毒了,但结果是,即使是错误变量也包含锁保护,它引用互斥体,因此不能返回。
您可以将错误Map到其他类型,例如:
字符串