@@ -180,6 +180,12 @@ use crate::time::Duration;
180
180
#[ macro_use]
181
181
mod local;
182
182
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
+
183
189
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
184
190
pub use self :: local:: { AccessError , LocalKey } ;
185
191
@@ -446,6 +452,20 @@ impl Builder {
446
452
F : FnOnce ( ) -> T ,
447
453
F : Send + ' a ,
448
454
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 ,
449
469
{
450
470
let Builder { name, stack_size } = self ;
451
471
@@ -456,7 +476,8 @@ impl Builder {
456
476
} ) ) ;
457
477
let their_thread = my_thread. clone ( ) ;
458
478
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 ) } ) ;
460
481
let their_packet = my_packet. clone ( ) ;
461
482
462
483
let output_capture = crate :: io:: set_output_capture ( None ) ;
@@ -480,10 +501,14 @@ impl Builder {
480
501
// closure (it is an Arc<...>) and `my_packet` will be stored in the
481
502
// same `JoinInner` as this closure meaning the mutation will be
482
503
// 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) } ;
484
505
} ;
485
506
486
- Ok ( JoinHandle ( JoinInner {
507
+ if let Some ( scope_data) = scope_data {
508
+ scope_data. increment_n_running_threads ( ) ;
509
+ }
510
+
511
+ Ok ( JoinInner {
487
512
// SAFETY:
488
513
//
489
514
// `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed
@@ -506,8 +531,8 @@ impl Builder {
506
531
) ?
507
532
} ,
508
533
thread : my_thread,
509
- packet : Packet ( my_packet) ,
510
- } ) )
534
+ packet : my_packet,
535
+ } )
511
536
}
512
537
}
513
538
@@ -1239,34 +1264,53 @@ impl fmt::Debug for Thread {
1239
1264
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1240
1265
pub type Result < T > = crate :: result:: Result < T , Box < dyn Any + Send + ' static > > ;
1241
1266
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).
1246
1271
//
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
+ }
1258
1302
1259
1303
/// Inner representation for JoinHandle
1260
- struct JoinInner < T > {
1304
+ struct JoinInner < ' scope , T > {
1261
1305
native : imp:: Thread ,
1262
1306
thread : Thread ,
1263
- packet : Packet < T > ,
1307
+ packet : Arc < Packet < ' scope , T > > ,
1264
1308
}
1265
1309
1266
- impl < T > JoinInner < T > {
1310
+ impl < ' scope , T > JoinInner < ' scope , T > {
1267
1311
fn join ( mut self ) -> Result < T > {
1268
1312
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 ( )
1270
1314
}
1271
1315
}
1272
1316
@@ -1333,7 +1377,7 @@ impl<T> JoinInner<T> {
1333
1377
/// [`thread::Builder::spawn`]: Builder::spawn
1334
1378
/// [`thread::spawn`]: spawn
1335
1379
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1336
- pub struct JoinHandle < T > ( JoinInner < T > ) ;
1380
+ pub struct JoinHandle < T > ( JoinInner < ' static , T > ) ;
1337
1381
1338
1382
#[ stable( feature = "joinhandle_impl_send_sync" , since = "1.29.0" ) ]
1339
1383
unsafe impl < T > Send for JoinHandle < T > { }
@@ -1407,7 +1451,7 @@ impl<T> JoinHandle<T> {
1407
1451
/// function has returned, but before the thread itself has stopped running.
1408
1452
#[ unstable( feature = "thread_is_running" , issue = "90470" ) ]
1409
1453
pub fn is_running ( & self ) -> bool {
1410
- Arc :: strong_count ( & self . 0 . packet . 0 ) > 1
1454
+ Arc :: strong_count ( & self . 0 . packet ) > 1
1411
1455
}
1412
1456
}
1413
1457
0 commit comments