multithreading - 通过将 FnMut 包装成 Weak 将其发送到其他线程> 抱怨缺少发送
问题描述
我正在尝试用事件和回调编写一个简单的观察者模式。这个想法是,当拥有变异函数的事物死亡 ( struct Obj {cb: Arc<Mutex<FnMut>>, .. }
) 时,它会丢弃Arc
. 之后,任何Weak
引用都将(有效地)失效,并且可以在访问时检测到。我也希望这能将FnMut
fromThread
的'static
生命周期解耦。我可能需要将整个东西包装在另一个Arc<Rwlock<T>>
中,以防止Weak
引用做线程不安全的事情,但这是一个不同的问题。
我得到的最接近的解决方案是:如何将函数发送到另一个线程?
但是,我似乎拥有Arc<Mutex<T>>
并增加了生命周期(尽管我可能做错了)似乎没有帮助。我有点迷茫到底什么是错的。
我写了一个最小的例子:
use std::{
collections::HashMap,
sync::{
mpsc::{self, Receiver},
Arc, Mutex, Weak,
},
thread::{self, JoinHandle},
};
struct Callback {
cb_w: Weak<Mutex<FnMut()>>,
}
type FnMapping = Arc<HashMap<String, Callback>>;
fn start_thread<'a>(rx: Receiver<String>, mapping: FnMapping) -> JoinHandle<()> {
thread::spawn(move || {
match rx.recv() {
Ok(v) => {
if let Some(o) = mapping.get(&v) {
match o.cb_w.upgrade() {
Some(cb_m) => match cb_m.lock() {
Ok(cb_lg) => (*cb_lg)(),
Err(e) => (),
},
None => { /* TODO owner is gone, mark for delete */ }
}
}
}
Err(e) => (),
}
})
}
fn main() {
let mapping: FnMapping = Arc::new(HashMap::new());
let (tx, rx) = mpsc::channel();
drop(tx);
start_thread(rx, mapping)
.join()
.expect("Could not join thread -- failed to terminate?");
println!("Leaving the test bay.");
}
这无法编译并出现以下错误:
error[E0277]: `(dyn std::ops::FnMut() + 'static)` cannot be sent between threads safely
--> src/main.rs:17:5
|
17 | thread::spawn(move || {
| ^^^^^^^^^^^^^ `(dyn std::ops::FnMut() + 'static)` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `(dyn std::ops::FnMut() + 'static)`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Mutex<(dyn std::ops::FnMut() + 'static)>`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Weak<std::sync::Mutex<(dyn std::ops::FnMut() + 'static)>>`
= note: required because it appears within the type `Callback`
= note: required because it appears within the type `(std::string::String, Callback)`
= note: required because it appears within the type `std::marker::PhantomData<(std::string::String, Callback)>`
= note: required because it appears within the type `std::collections::hash::table::RawTable<std::string::String, Callback>`
= note: required because it appears within the type `std::collections::HashMap<std::string::String, Callback>`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<std::collections::HashMap<std::string::String, Callback>>`
= note: required because it appears within the type `[closure@src/main.rs:17:19: 32:6 rx:std::sync::mpsc::Receiver<std::string::String>, mapping:std::sync::Arc<std::collections::HashMap<std::string::String, Callback>>]`
= note: required by `std::thread::spawn`
解决方案
推荐阅读
- android - 为什么更新android gradle后出现错误?
- python - 构建 GUI 项目 + cairo
- java - Maven 使用“mvn install”命令构建失败
- c# - 在查询中使用 `DbFunctions.DiffDays(DateTime.Now, c.ModifiedDate)` 时,尽管表中有数据,实体框架仍返回 0 个结果
- swift - 未调用 UISeachController 委托方法,搜索栏无法成为第一响应者
- react-native - 特定选项卡上的 React Navigation 更新屏幕
- angular-material - Angular 5 是否支持 Angular 材质最新版本(7)
- amazon-s3 - 如何将大量小型 CSV 文件从 s3 加载到 redshift?
- python - 无论如何都可以根据条件使用 PrettyTable 来设置元素样式
- mysql - 在 CentOS 7 上重置 MySQL 8.0 密码