leak_playground_std/
thread.rs1use std::thread::JoinHandle;
17use std::{marker::PhantomData, thread};
18
19use crate::marker::{Forget, Unforget};
20use crate::mem::{self, ManuallyDrop};
21use crate::rc::Rc;
22use crate::sync::Arc;
23
24pub fn spawn_scoped<'a, F, T>(f: F) -> JoinGuard<'a, T>
26where
27 F: FnOnce() -> T + Send + 'a,
28 T: Send + 'a,
29{
30 JoinGuard {
31 child: unsafe {
33 ManuallyDrop::new_unchecked(thread::Builder::new().spawn_unchecked(f).unwrap())
34 },
35 _borrow: Unforget::new(PhantomData),
36 _unsend: PhantomData,
37 }
38}
39
40pub struct JoinGuard<'a, T> {
47 child: ManuallyDrop<thread::JoinHandle<T>>,
48
49 _borrow: Unforget<'static, PhantomData<&'a ()>>,
51 _unsend: PhantomData<*mut ()>,
52}
53
54unsafe impl<T> Send for JoinGuard<'_, T> where Self: Forget {}
55unsafe impl<T> Sync for JoinGuard<'_, T> {}
56
57impl<T> JoinGuard<'_, T> {
58 pub fn join(mut self) -> std::thread::Result<T> {
59 let join_handle;
60 unsafe {
62 join_handle = ManuallyDrop::take(&mut self.child);
63 mem::forget_unchecked(self);
65 }
66 join_handle.join()
67 }
68
69 pub fn thread(&self) -> &std::thread::Thread {
70 self.child.thread()
71 }
72
73 pub fn is_finished(&self) -> bool {
74 self.child.is_finished()
75 }
76
77 pub fn into_rc(self) -> Rc<Self> {
78 unsafe { Rc::new_unchecked(self) }
81 }
82
83 pub fn into_arc(self) -> Arc<Self> {
84 unsafe { Arc::new_unchecked(self) }
87 }
88}
89
90impl<T> JoinGuard<'static, T> {
91 pub fn into_handle(self) -> JoinHandle<T> {
92 self.into()
93 }
94
95 pub fn detach(self) {
96 let _ = self.into_handle();
97 }
98}
99
100impl<T> From<JoinGuard<'static, T>> for JoinHandle<T> {
101 fn from(mut value: JoinGuard<'static, T>) -> Self {
102 unsafe { ManuallyDrop::take(&mut value.child) }
103 }
104}
105
106impl<'a, T> Drop for JoinGuard<'a, T> {
107 fn drop(&mut self) {
108 let join_handle = unsafe { ManuallyDrop::take(&mut self.child) };
109 let child = join_handle.thread().clone();
111 let res = join_handle.join();
114 if res.is_err() && !std::thread::panicking() {
118 panic!("child thread {child:?} panicked");
119 }
120 }
121}