你怎么发送Vec切片到生锈的任务?

Dou*_*oug 2 rust

所以,这不起作用:

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 >>可能是解决方案,但即使这样,创建的切片也将具有本地生命周期.

我可以使用不安全的代码来转换生命周期(这确实有效),但有没有办法安全地做同样的事情?

围栏:http://is.gd/WQBdSB

Fra*_*gné 8

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用来欺骗生命周期,但这是不安全的.

  • @Doug,它仍然不安全,因为拥有向量的任务可能会在子任务完成之前消失(并释放向量)。这里不仅仅存在数据竞争。 (2认同)
  • @Doug:是的.任务的生命周期之间没有任何关系.看我的编辑. (2认同)