#threads closures

6 messages · Page 1 of 1 (latest)

plain cloak
#

Well what is happening is that closure borrows x and x has a lifetime which lives beyond the thread::spawn and gets drops at the end of the main function so internally the closure will borrow both the lifetime of x and x itself basically the closure's lifetime will also be the same as x so yes even if the thread spawned gets dropped the closure does not because it gets dropped at the same way as x gets dropped which is at the end of the main function.

Now when you write move closure it will basically move the x completely inside the thread like it will take ownership of it now what that means is that the lifetime of x will be the same as that of the closure like in other words the closure's lifetime will not get updated to that of x so when the thread ends so the closure and x both get dropped.

I hope you got the whole idea 🙂

deft drum
#

There are scoped threads if you need to borrow data from the local scope

#
use std::thread;
use std::sync::atomic::Ordering;

fn main() {
    let x: std::sync::atomic::AtomicU8 = 1.into();
    thread::scope(|scope| {
        for _ in 0..20 {
            scope.spawn(|| {
                x.store(x.load(Ordering::Relaxed) + 1, Ordering::Relaxed);
                println!("x is {}", x.load(Ordering::Relaxed));
            });
        }
    });
}
hoary escarp
#

… as spawned threads die with the main function?

This is an incorrect assumption. Spawned threads don't die when the main function returns. Rather, they die when the process is terminated, which is something that is done by code that main() returns to. So, the order of events is backwards from what you are thinking: it's not that threads are killed as part of the cleanup in main(), but that threads are killed after main() has returned. Therefore, threads can't soundly borrow anything in main(), because there is a window of time where the things in main() are gone but spawned threads aren't.

(It's also possible to outright call main() a second time like any other function, which makes the window big, but it would exist even if that were not true.)

hoary escarp
#

usually it returns to a function provided by the compiler/stdlib (often called _start) whose responsibility is to interface between whatever the OS requirements are and the function signature of your main(). all the details are platform-specific

#

The important part, though, is that returning from main is not a special operation. It proceeds exactly like any other Rust function return, and that means that all the local variables get dropped and then deallocated. Nothing is inserted to kill other threads before the drops.