So, this doesn\'t work:
use std::comm;
#[deriving(Show)]
struct St { v: u8 }
fn main() {
let mut foo:Vec = Vec::new();
for i in range(0u8, 1
Rust prevents you from having mutable access to the same value from within multiple tasks, because that leads to data races. Specifically, a task can't have borrowed pointers (incl. slices) to a value that is owned by another task.
To allow multiple tasks to access the same object, you should use Arc<T>. To provide mutable access to the object, put a RefCell<T> in that Arc
: Arc<RefCell<T>>
. As for that T
, you can't use a slice type, as I just explained. I suggest you create 2 different Arc<RefCell<Vec<St>>>
objects, send a clone of an Arc<RefCell<Vec<St>>>
on the channel and join the Vec
s when the tasks have done their job.
In general, when doing parallel algorithms, you should avoid mutating shared state. This leads to poor performance, because the system needs to invalidate memory caches across cores. If possible, consider having the task allocate and hold on to its result until it's complete, and send the complete result over a channel, rather than a mere bool
.
EDIT
We can reformulate your initial program in terms of ownership to understand why it's not sound. The stack frame for the call to main
owns foo
, the Vec
. foo_slice
, f1
and f2
borrow that Vec
. You spawn a task. That task may outlive the call frame for main
, and even outlive the task that spawned it. Therefore, it is illegal to send references to values that are constrained to a stack frame. This is why borrowed pointers, with the exception of &'static T
, don't fulfill Send.
Boxing the Vec
changes nothing, because the stack frame still owns the Box
, so returning from the function will drop the box and its contents.
The compiler cannot verify that the task won't outlive the owner of the values you send references to to the task. If you are sure that the task will terminate before the references you give it become invalid, you can use transmute to cheat on the lifetime, but this is unsafe.