ust*_*ion 4 multithreading rust
我无法在线程之间共享引用.
trait Facade { /*some functions*/ }
struct Client<'a> {
facade: &'a mut Facade,
join_grd: thread::JoinGuard<'a()>,
}
impl<'a> Client<'a> {
pub fn new(my_facade: &'a mut Facade) -> Client<'a> {
Client {
facade: my_facade,
join_grd: thread::scoped(|| Client::start(my_facade)),
}
}
fn start(my_facade: &'a mut Facade) { unimplemented!() }
}
Run Code Online (Sandbox Code Playgroud)
鉴于我在Rust中的新手状态,我对概念和错误感到困惑.我如何实现上述目标?
由于Rust中的可变别名保证,我很确定你不能这样做.在Rust中,你不能同时对同一个东西进行两次可变引用,但这正是你的代码中发生的事情:你存储my_facade到字段中Client,同时你试图将它传递给start()另一个中的方法线.这将需要对Facade不允许的两个可变引用.
编译器在您的代码上发出的实际错误是由于您使用的是非移动闭包.如果您将thread::scoped()实例化更改为:
join_grd: thread::scoped(move || Client::start(my_facade))
Run Code Online (Sandbox Code Playgroud)
错误会更明智:
test.rs:16:60: 16:69 error: cannot move `my_facade` into closure because it is borrowed
test.rs:16 join_grd: thread::scoped(move || Client::start(my_facade))
^~~~~~~~~
test.rs:15:21: 15:30 note: borrow of `*my_facade` occurs here
test.rs:15 facade: my_facade,
^~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
这实际上意味着由于&mut引用是唯一的并且被移动而不是复制,因此您无法复制它们.类似的代码与常规&引用而不是&mut(以及一个额外的Sync父特征Facade)工作正常.
您必须重新考虑您的体系结构以修复此错误.单独从这段代码中很难理解你想要什么,所以我不能给出任何确切的建议,但你可以考虑使用Arc,Mutex如果你想在线程之间共享可变状态.
天真的用法Arc/Mutex如下:
fn start(my_facade: Arc<Mutex<Facade>>)
Run Code Online (Sandbox Code Playgroud)
不会起作用,因为它Facade是一种特质,而不是常规类型.当您使用traits作为类型时,您实际上选择以trait对象的形式进行动态调度.简而言之,特征对象不能直接使用; 他们应该总是在指针后面.您的原始程序也使用了特征对象(&'a mut Facade是一个特征对象).理想情况下,我们应该能够使用任何类型的智能指针形成特征对象,理想情况下Arc<Mutex<Facade>>应该可以工作,但遗憾的是现在特征对象只能用&,&mut或者Box:
fn start(my_facade: Arc<Mutex<Box<Facade>>>)
Run Code Online (Sandbox Code Playgroud)
这就是Sized你观察到的错误的原因.
但是,您还应该考虑不使用trait对象,只使用泛型:
trait Facade: Send { fn f(&self); }
struct Client<'a, F: Facade> { // '
facade: Arc<Mutex<F>>,
join_grd: thread::JoinGuard<'a, ()>, // '
}
impl<'a, F: Facade+'a> Client<'a, F> { // '
pub fn new(my_facade: Arc<Mutex<F>>) -> Client<'a, F> { // '
let my_facade_2 = my_facade.clone(); // clone the Arc pointer
Client {
facade: my_facade,
join_grd: thread::scoped(move || Client::start(my_facade_2)),
}
}
fn start(my_facade: Arc<Mutex<F>>) { unimplemented!() }
}
Run Code Online (Sandbox Code Playgroud)
你还需要添加Send结合要么在性状本身(如在上面的例子中)或在F类型变量(如在F: Facade+Send+'a),因为只有Send数据可以线程之间传输安全,所以需要指定F是Send,无论是直接或作为supertrait约束Facade.
| 归档时间: |
|
| 查看次数: |
342 次 |
| 最近记录: |