Reputation: 801
Why doesn't Example 1 compile given that Example 2 compiles just fine? The only difference between the examples is that in Example 1 value
is a function local variable, and in Example 2 value
is an argument to the function.
Example 1
#![feature(scoped)]
use std::thread;
use std::sync::atomic::{AtomicUsize, Ordering};
pub fn foo<F>() {
let mut join_guards = Vec::new();
let value = AtomicUsize::new(0);
for _ in 0..10 {
join_guards.push(thread::scoped(|| {
value.fetch_add(1, Ordering::SeqCst);
}));
}
}
Example 2
#![feature(scoped)]
use std::thread;
use std::sync::atomic::{AtomicUsize, Ordering};
pub fn foo<F>(value: AtomicUsize) {
let mut join_guards = Vec::new();
for _ in 0..10 {
join_guards.push(thread::scoped(|| {
value.fetch_add(1, Ordering::SeqCst);
}));
}
}
These are the error messages I get trying to compile Example 1:
error: `value` does not live long enough
join_guards.push(thread::scoped(|| {
value.fetch_add(1, Ordering::SeqCst);
}));
note: reference must be valid for the block at 6:20...
pub fn foo<F>() {
let mut join_guards = Vec::new();
let value = AtomicUsize::new(0);
for _ in 0..10 {
join_guards.push(thread::scoped(|| {
note: ...but borrowed value is only valid for the block suffix following statement 1 at 8:40
let value = AtomicUsize::new(0);
for _ in 0..10 {
join_guards.push(thread::scoped(|| {
value.fetch_add(1, Ordering::SeqCst);
}));
Upvotes: 2
Views: 106
Reputation: 90902
join_guards
is a vector of scoped threads with a certain shared lifetime. That lifetime is determined by which variables it closes over: value
is the only one. Therefore, the lifetime of the scoped threads is the scope of value
. Where is value
legal? After it is defined and until it goes out of scope—that is, “the block suffix following statement 1 at 8:40”. join_guards
must have as its lifetime a lifetime no greater than this, but if join_guards
is defined before value
, this is not the case.
The solution is to reverse the order of declaration:
let value = AtomicUsize::new(0);
let mut join_guards = Vec::new();
This explains why the second example works, also.
Upvotes: 3