所以,这不起作用:
use std::comm;
#[deriving(Show)]
struct St { v: u8 }
fn main() {
let mut foo:Vec<St> = Vec::new();
for i in range(0u8, 10) {
foo.push(St { v: i });
}
{
let mut foo_slice = foo.as_mut_slice();
let (f1, f2) = foo_slice.split_at_mut(5);
let (sl, rx):(Sender<Option<&mut [St]>>, Receiver<Option<&mut [St]>>) = comm::channel();
let (sx, rl):(Sender<bool>, Receiver<bool>) = comm::channel();
spawn(proc() {
loop {
let v = rx.recv();
match v {
Some(v) => {
v[0].v = 100u8;
sx.send(true);
},
None => {
sx.send(false);
break;
}
}
}
});
sl.send(Some(f1));
sl.send(Some(f2));
sl.send(None);
println!("{}", rl.recv());
println!("{}", rl.recv());
println!("{}", rl.recv());
}
println!("{}", foo);
}
Run Code Online (Sandbox Code Playgroud)
...因为:
sl.send(Some(f1));
sl.send(Some(f2));
sl.send(None);
Run Code Online (Sandbox Code Playgroud)
推断变量f1和f2必须是'静态的,因为任务可能比它正在运行的函数寿命更长.这反过来意味着foo必须是'静态的,而不是'a,这是main()的生命周期.
因此有点奇怪的错误:
<anon>:14:27: 14:30 error: `foo` does not live long enough
<anon>:14 let mut foo_slice = foo.as_mut_slice();
^~~
note: reference must be valid for the static lifetime...
<anon>:6:11: 46:2 note: ...but borrowed value is only valid for the block at 6:10
<anon>:6 fn main() {
<anon>:7
<anon>:8 let mut foo:Vec<St> = Vec::new();
<anon>:9 for i in range(0u8, 10) {
<anon>:10 foo.push(St { v: i });
<anon>:11 }
Run Code Online (Sandbox Code Playgroud)
所以,为了解决这个问题,我认为使用Box <Vec <Foo >>可能是解决方案,但即使这样,创建的切片也将具有本地生命周期.
我可以使用不安全的代码来转换生命周期(这确实有效),但有没有办法安全地做同样的事情?
Rust阻止您对多个任务中的相同值进行可变访问,因为这会导致数据争用.具体来说,任务不能将指针(包括切片)借用到另一个任务所拥有的值.
要允许多个任务访问同一个对象,您应该使用Arc<T>.要提供对对象的可变访问,请RefCell<T>在Arc:Arc<RefCell<T>>.至于那个T,你不能像我刚才解释的那样使用切片类型.我建议你创建2个不同的Arc<RefCell<Vec<St>>>对象,Arc<RefCell<Vec<St>>>在通道上发送一个克隆,并Vec在任务完成工作时加入s.
通常,在进行并行算法时,应避免改变共享状态.这会导致性能不佳,因为系统需要使内核中的内存缓存无效.如果可能,考虑让任务分配并保持其结果直到完成,并通过通道发送完整的结果,而不仅仅是bool.
编辑
我们可以根据所有权重新制定您的初始计划,以了解为什么它不合理.main拥有调用的堆栈框架foo,Vec.foo_slice,f1并f2借用Vec.你产生了一个任务.该任务可能比main生成它的任务更长,甚至比生成它的任务更长.因此,发送对受限于堆栈帧的值的引用是非法的.这就是为什么借用指针,除了&'static T,没有实现Send.
拳击Vec变化没什么,因为堆栈帧仍然拥有Box,所以从函数返回将丢弃框及其内容.
编译器无法验证任务是否不会超过您发送对任务的引用值的所有者.如果你确定任务将在你给它的引用变为无效之前终止,你可以transmute用来欺骗生命周期,但这是不安全的.
| 归档时间: |
|
| 查看次数: |
941 次 |
| 最近记录: |