I am reading a string from a file, splitting it by lines into a vector and then I want to do something with the extracted lines in separate threads. Like this:
use std::fs::File;
use std::io::prelude::*;
use std::thread;
fn main() {
match File::open("data") {
Ok(mut result) => {
let mut s = String::new();
result.read_to_string(&mut s);
let k : Vec<_> = s.split("\n").collect();
for line in k {
thread::spawn(move || {
println!("nL: {:?}", line);
});
}
}
Err(err) => {
println!("Error {:?}",err);
}
}
}
Of course this throws an error, because s
will go out of scope before the threads are started:
error[E0597]: `s` does not live long enough
--> src/main.rs:9:30
|
7 | let mut s = String::new();
| ----- binding `s` declared here
8 | result.read_to_string(&mut s);
9 | let k : Vec<_> = s.split("\n").collect();
| ^------------
| |
| borrowed value does not live long enough
| argument requires that `s` is borrowed for `'static`
...
16 | }
| - `s` dropped here while still borrowed
What can I do now? I've tried many things like Box
or Arc
, but I couldn't get it working. I somehow need to create a copy of s
which also lives in the threads. But how do I do that?
The problem, fundamentally, is that line
is a borrowed slice into s
. There's really nothing you can do here, since there's no way to guarantee that each line
will not outlive s
itself.
Also, just to be clear: there is absolutely no way in Rust to "extend the lifetime of a variable". It simply cannot be done.
The simplest way around this is to go from line
being borrowed to owned. Like so:
use std::thread;
fn main() {
let mut s: String = "One\nTwo\nThree\n".into();
let k : Vec<String> = s.split("\n").map(|s| s.into()).collect();
for line in k {
thread::spawn(move || {
println!("nL: {:?}", line);
});
}
}
The .map(|s| s.into())
converts from &str
to String
. Since a String
owns its contents, it can be safely moved into each thread's closure, and will live independently of the thread that created it.
Note: you could do this in nightly Rust using the new scoped thread API, but that is still unstable.