For me, msg could have same lifetime as manager.
Yes. That means msg
lives as long as the enclosing function does:
let child = thread::spawn(move || {
// <— thread_manager moved into and owned by the function
let msg = thread_manager.make();
thread_tx.send(msg).unwrap();
println!("thread {} finished", id);
// <— thread_manager is dropped here so `msg` becomes invalid
});
there's no telling when the message will actually be received / used, but it'll likely be after the thread has died. And rustc can't assume any other instance of the manager will remain alive at this point, so it has to assume it'll be left with a dangling reference.
Why doesn't msg
just use an Arc<Manager>
, or even a Weak<Manager>
? (though the latter doesn't seem like a great idea here).
You might be able to do something along those lines of what you're attempting (without even Arc
I believe) using scoped threads, but the stdlib's are not scoped, as far as the compiler is concerned there is no lifetime relationship between the caller and contents of a spawn
call, they live completely independent lives, and can run and stop in any order (even if you use join
). So the reasoning about thread-bound lifetimes is completely local.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…