@@ -180,6 +180,12 @@ use crate::time::Duration;
180180#[ macro_use]
181181mod local;
182182
183+ #[ unstable( feature = "scoped_threads" , issue = "none" ) ]
184+ mod scoped;
185+
186+ #[ unstable( feature = "scoped_threads" , issue = "none" ) ]
187+ pub use scoped:: { scope, Scope , ScopedJoinHandle } ;
188+
183189#[ stable( feature = "rust1" , since = "1.0.0" ) ]
184190pub use self :: local:: { AccessError , LocalKey } ;
185191
@@ -446,6 +452,20 @@ impl Builder {
446452 F : FnOnce ( ) -> T ,
447453 F : Send + ' a ,
448454 T : Send + ' a ,
455+ {
456+ Ok ( JoinHandle ( unsafe { self . spawn_unchecked_ ( f, None ) } ?) )
457+ }
458+
459+ unsafe fn spawn_unchecked_ < ' a , ' scope , F , T > (
460+ self ,
461+ f : F ,
462+ scope_data : Option < & ' scope scoped:: ScopeData > ,
463+ ) -> io:: Result < JoinInner < ' scope , T > >
464+ where
465+ F : FnOnce ( ) -> T ,
466+ F : Send + ' a ,
467+ T : Send + ' a ,
468+ ' scope : ' a ,
449469 {
450470 let Builder { name, stack_size } = self ;
451471
@@ -456,7 +476,8 @@ impl Builder {
456476 } ) ) ;
457477 let their_thread = my_thread. clone ( ) ;
458478
459- let my_packet: Arc < UnsafeCell < Option < Result < T > > > > = Arc :: new ( UnsafeCell :: new ( None ) ) ;
479+ let my_packet: Arc < Packet < ' scope , T > > =
480+ Arc :: new ( Packet { scope : scope_data, result : UnsafeCell :: new ( None ) } ) ;
460481 let their_packet = my_packet. clone ( ) ;
461482
462483 let output_capture = crate :: io:: set_output_capture ( None ) ;
@@ -480,10 +501,14 @@ impl Builder {
480501 // closure (it is an Arc<...>) and `my_packet` will be stored in the
481502 // same `JoinInner` as this closure meaning the mutation will be
482503 // safe (not modify it and affect a value far away).
483- unsafe { * their_packet. get ( ) = Some ( try_result) } ;
504+ unsafe { * their_packet. result . get ( ) = Some ( try_result) } ;
484505 } ;
485506
486- Ok ( JoinHandle ( JoinInner {
507+ if let Some ( scope_data) = scope_data {
508+ scope_data. increment_n_running_threads ( ) ;
509+ }
510+
511+ Ok ( JoinInner {
487512 // SAFETY:
488513 //
489514 // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed
@@ -506,8 +531,8 @@ impl Builder {
506531 ) ?
507532 } ,
508533 thread : my_thread,
509- packet : Packet ( my_packet) ,
510- } ) )
534+ packet : my_packet,
535+ } )
511536 }
512537}
513538
@@ -1239,34 +1264,53 @@ impl fmt::Debug for Thread {
12391264#[ stable( feature = "rust1" , since = "1.0.0" ) ]
12401265pub type Result < T > = crate :: result:: Result < T , Box < dyn Any + Send + ' static > > ;
12411266
1242- // This packet is used to communicate the return value between the spawned thread
1243- // and the rest of the program. Memory is shared through the `Arc` within and there's
1244- // no need for a mutex here because synchronization happens with `join()` (the
1245- // caller will never read this packet until the thread has exited).
1267+ // This packet is used to communicate the return value between the spawned
1268+ // thread and the rest of the program. It is shared through an `Arc` and
1269+ // there's no need for a mutex here because synchronization happens with `join()`
1270+ // (the caller will never read this packet until the thread has exited).
12461271//
1247- // This packet itself is then stored into a `JoinInner` which in turns is placed
1248- // in `JoinHandle` and `JoinGuard`. Due to the usage of `UnsafeCell` we need to
1249- // manually worry about impls like Send and Sync. The type `T` should
1250- // already always be Send (otherwise the thread could not have been created) and
1251- // this type is inherently Sync because no methods take &self. Regardless,
1252- // however, we add inheriting impls for Send/Sync to this type to ensure it's
1253- // Send/Sync and that future modifications will still appropriately classify it.
1254- struct Packet < T > ( Arc < UnsafeCell < Option < Result < T > > > > ) ;
1255-
1256- unsafe impl < T : Send > Send for Packet < T > { }
1257- unsafe impl < T : Sync > Sync for Packet < T > { }
1272+ // An Arc to the packet is stored into a `JoinInner` which in turns is placed
1273+ // in `JoinHandle`. Due to the usage of `UnsafeCell` we need to manually worry
1274+ // about impls like Send and Sync. The type `T` should already always be Send
1275+ // (otherwise the thread could not have been created) and this type is
1276+ // inherently Sync because no methods take &self. Regardless, however, we add
1277+ // inheriting impls for Send/Sync to this type to ensure it's Send/Sync and
1278+ // that future modifications will still appropriately classify it.
1279+ struct Packet < ' scope , T > {
1280+ scope : Option < & ' scope scoped:: ScopeData > ,
1281+ result : UnsafeCell < Option < Result < T > > > ,
1282+ }
1283+
1284+ unsafe impl < ' scope , T : Send > Send for Packet < ' scope , T > { }
1285+ unsafe impl < ' scope , T : Sync > Sync for Packet < ' scope , T > { }
1286+
1287+ impl < ' scope , T > Drop for Packet < ' scope , T > {
1288+ fn drop ( & mut self ) {
1289+ if let Some ( scope) = self . scope {
1290+ // If this packet was for a thread that ran in a scope, the thread
1291+ // panicked, and nobody consumed the panic payload, we put the
1292+ // panic payload in the scope so it can re-throw it, if it didn't
1293+ // already capture any panic yet.
1294+ if let Some ( Err ( e) ) = self . result . get_mut ( ) . take ( ) {
1295+ scope. panic_payload . lock ( ) . unwrap ( ) . get_or_insert ( e) ;
1296+ }
1297+ // Book-keeping so the scope knows when it's done.
1298+ scope. decrement_n_running_threads ( ) ;
1299+ }
1300+ }
1301+ }
12581302
12591303/// Inner representation for JoinHandle
1260- struct JoinInner < T > {
1304+ struct JoinInner < ' scope , T > {
12611305 native : imp:: Thread ,
12621306 thread : Thread ,
1263- packet : Packet < T > ,
1307+ packet : Arc < Packet < ' scope , T > > ,
12641308}
12651309
1266- impl < T > JoinInner < T > {
1310+ impl < ' scope , T > JoinInner < ' scope , T > {
12671311 fn join ( mut self ) -> Result < T > {
12681312 self . native . join ( ) ;
1269- Arc :: get_mut ( & mut self . packet . 0 ) . unwrap ( ) . get_mut ( ) . take ( ) . unwrap ( )
1313+ Arc :: get_mut ( & mut self . packet ) . unwrap ( ) . result . get_mut ( ) . take ( ) . unwrap ( )
12701314 }
12711315}
12721316
@@ -1333,7 +1377,7 @@ impl<T> JoinInner<T> {
13331377/// [`thread::Builder::spawn`]: Builder::spawn
13341378/// [`thread::spawn`]: spawn
13351379#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1336- pub struct JoinHandle < T > ( JoinInner < T > ) ;
1380+ pub struct JoinHandle < T > ( JoinInner < ' static , T > ) ;
13371381
13381382#[ stable( feature = "joinhandle_impl_send_sync" , since = "1.29.0" ) ]
13391383unsafe impl < T > Send for JoinHandle < T > { }
@@ -1407,7 +1451,7 @@ impl<T> JoinHandle<T> {
14071451 /// function has returned, but before the thread itself has stopped running.
14081452 #[ unstable( feature = "thread_is_running" , issue = "90470" ) ]
14091453 pub fn is_running ( & self ) -> bool {
1410- Arc :: strong_count ( & self . 0 . packet . 0 ) > 1
1454+ Arc :: strong_count ( & self . 0 . packet ) > 1
14111455 }
14121456}
14131457
0 commit comments