Reputation: 3437
Considering the following code, I wish to have access to both client
and requests
within my thread, currently I do not:
for _x in 0..100 {
let handle = thread::spawn(move || {
let start = time::precise_time_s();
let res = client.get("http://jacob.uk.com")
.header(Connection::close())
.send().unwrap();
let end = time::precise_time_s();
requests.push(Request::new(end-start));
});
handle.join().unwrap()
}
I get the following compiler error:
Compiling Herd v0.1.0 (file:///Users/jacobclark/Desktop/LearningRust/Herd)
src/main.rs:41:23: 41:29 error: capture of moved value: `client`
src/main.rs:41 let res = client.get("http://jacob.uk.com")
^~~~~~
src/main.rs:38:41: 48:10 note: `client` moved into closure environment here because it has type `[closure(())]`, which is non-copyable
src/main.rs:38 let handle = thread::spawn(move || {
src/main.rs:39 let start = time::precise_time_s();
src/main.rs:40
src/main.rs:41 let res = client.get("http://jacob.uk.com")
src/main.rs:42 .header(Connection::close())
src/main.rs:43 .send().unwrap();
...
src/main.rs:38:41: 48:10 help: perhaps you meant to use `clone()`?
src/main.rs:47:13: 47:21 error: capture of moved value: `requests`
src/main.rs:47 requests.push(Request::new(end-start));
^~~~~~~~
src/main.rs:38:41: 48:10 note: `requests` moved into closure environment here because it has type `[closure(())]`, which is non-copyable
src/main.rs:38 let handle = thread::spawn(move || {
src/main.rs:39 let start = time::precise_time_s();
src/main.rs:40
src/main.rs:41 let res = client.get("http://jacob.uk.com")
src/main.rs:42 .header(Connection::close())
src/main.rs:43 .send().unwrap();
...
src/main.rs:38:41: 48:10 help: perhaps you meant to use `clone()`?
src/main.rs:53:24: 53:32 error: use of moved value: `requests`
src/main.rs:53 Request::mean_time(requests);
^~~~~~~~
src/main.rs:38:41: 48:10 note: `requests` moved into closure environment here because it has type `[closure(())]`, which is non-copyable
src/main.rs:38 let handle = thread::spawn(move || {
src/main.rs:39 let start = time::precise_time_s();
src/main.rs:40
src/main.rs:41 let res = client.get("http://jacob.uk.com")
src/main.rs:42 .header(Connection::close())
src/main.rs:43 .send().unwrap();
...
src/main.rs:38:41: 48:10 help: perhaps you meant to use `clone()`?
error: aborting due to 3 previous errors
Could not compile `Herd`
.
Upvotes: 2
Views: 98
Reputation: 60127
Firstly, minimal examples are really useful:
use std::thread;
fn main() {
let mut items = Vec::new();
for _ in 0..100 {
thread::spawn(move || {
items.push(());
});
}
}
So what's the problem here? Well, you're moving items
into a closure 100 times - but you can only move it once!
To share data across multiple threads, you need
To remove data races - put it in a Mutex
(or don't mutate it).
To keep it alive - put it in an Arc
(Atomically Reference-Counted pointer).
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let items = Arc::new(Mutex::new(Vec::new()));
for _ in 0..10 {
let thread_items = items.clone();
let handle = thread::spawn(move || {
thread_items.lock().unwrap().push(());
});
handle.join().unwrap();
}
println!("{:?}", items);
}
Upvotes: 5