These are chat archives for rust-lang/rust

14th
Apr 2016
hi, what's the recommended abstraction for running things concurrently?
is std::thread considered to be low-level, or the right abstraction?
looking for something like tasks, futures, promises
basically I have this pattern:
let foo = ...
thread::spawn(move || { /* use foo */ });

and I get

foo does not live long enough
note: reference must be valid for the static lifetime...

I guess the concern is that the main thread could be finished before the other threads are done, and then the value would be gone?
I tried to wrap things in Arc... that made the errors even worse
what's the recommended approach?
Erik Hedvall
@Ogeon
Apr 14 2016 22:29

Yes, exactly. You can't borrow from one thread in another, so you will have to transfer the ownership of everything the new thread needs. Arc is good for when you need to use something in multiple threads, and it may be suitable for xdg_dirs. You have to clone the Arc in the parent thread, and then use the clone in the child thread:

let xdg_dirs = Arc::new(xdg::BaseDirectories::with_prefix("sbs").unwrap());
let xdg_dirs_clone = xdg_dirs.clone();
thread::spawn(move || { /* use xdg_dirs_clone here */ });
// etc..

Other things, that you only need in one thread, can just be used as they are, but storing references and the using those in the threads won't work. Take the reference from inside the threads, instead:

let openjdk_relative_path = PathBuf::from_iter(&[OPENJDK_PREFIX, OPENJDK_NAME]);
let openjdk_setup_thread = thread::spawn(move || {
    let openjdk_result = download_if_necessary(xdg_dirs, OPENJDK_CDN_URL, openjdk_relative_path.as_path());
    // etc..
}
Something I think you would be interested in is scoped threads. They will let you borrow from the parent thread, but with the limitation that they will block the parent until they are done. I think it would be fine in your case, since you are joining them anyway. It should have the same behavior, but with more freedom.