@@ -152,7 +152,7 @@ pub(super) struct Registry {
152
152
// - when `join()` or `scope()` is invoked, similarly, no adjustments are needed.
153
153
// These are always owned by some other job (e.g., one injected by `ThreadPool::install()`)
154
154
// and that job will keep the pool alive.
155
- terminate : CountLatch ,
155
+ terminate_count : AtomicUsize ,
156
156
}
157
157
158
158
/// ////////////////////////////////////////////////////////////////////////
@@ -238,7 +238,7 @@ impl Registry {
238
238
thread_infos : stealers. into_iter ( ) . map ( ThreadInfo :: new) . collect ( ) ,
239
239
sleep : Sleep :: new ( logger, n_threads) ,
240
240
injected_jobs : Injector :: new ( ) ,
241
- terminate : CountLatch :: new ( ) ,
241
+ terminate_count : AtomicUsize :: new ( 1 ) ,
242
242
panic_handler : builder. take_panic_handler ( ) ,
243
243
start_handler : builder. take_start_handler ( ) ,
244
244
exit_handler : builder. take_exit_handler ( ) ,
@@ -390,8 +390,9 @@ impl Registry {
390
390
// drops) a `ThreadPool`; and, in that case, they cannot be
391
391
// calling `inject()` later, since they dropped their
392
392
// `ThreadPool`.
393
- debug_assert ! (
394
- !self . terminate. as_core_latch( ) . probe( ) ,
393
+ debug_assert_ne ! (
394
+ self . terminate_count. load( Ordering :: Acquire ) ,
395
+ 0 ,
395
396
"inject() sees state.terminate as true"
396
397
) ;
397
398
@@ -522,7 +523,7 @@ impl Registry {
522
523
/// terminate count and is responsible for invoking `terminate()`
523
524
/// when finished.
524
525
pub ( super ) fn increment_terminate_count ( & self ) {
525
- let previous = self . terminate . increment ( ) ;
526
+ let previous = self . terminate_count . fetch_add ( 1 , Ordering :: AcqRel ) ;
526
527
debug_assert ! ( previous != 0 , "registry ref count incremented from zero" ) ;
527
528
assert ! (
528
529
previous != std:: usize :: MAX ,
@@ -534,9 +535,9 @@ impl Registry {
534
535
/// dropped. The worker threads will gradually terminate, once any
535
536
/// extant work is completed.
536
537
pub ( super ) fn terminate ( & self ) {
537
- if self . terminate . set ( ) {
538
- for i in 0 .. self . num_threads ( ) {
539
- self . notify_worker_latch_is_set ( i) ;
538
+ if self . terminate_count . fetch_sub ( 1 , Ordering :: AcqRel ) == 1 {
539
+ for ( i , thread_info ) in self . thread_infos . iter ( ) . enumerate ( ) {
540
+ thread_info . terminate . set_and_tickle_one ( self , i) ;
540
541
}
541
542
}
542
543
}
@@ -562,6 +563,15 @@ struct ThreadInfo {
562
563
/// until workers have stopped; only used for tests.
563
564
stopped : LockLatch ,
564
565
566
+ /// The latch used to signal that terminated has been requested.
567
+ /// This latch is *set* by the `terminate` method on the
568
+ /// `Registry`, once the registry's main "terminate" counter
569
+ /// reaches zero.
570
+ ///
571
+ /// NB. We use a `CountLatch` here because it has no lifetimes and is
572
+ /// meant for async use, but the count never gets higher than one.
573
+ terminate : CountLatch ,
574
+
565
575
/// the "stealer" half of the worker's deque
566
576
stealer : Stealer < JobRef > ,
567
577
}
@@ -571,6 +581,7 @@ impl ThreadInfo {
571
581
ThreadInfo {
572
582
primed : LockLatch :: new ( ) ,
573
583
stopped : LockLatch :: new ( ) ,
584
+ terminate : CountLatch :: new ( ) ,
574
585
stealer,
575
586
}
576
587
}
@@ -817,12 +828,12 @@ unsafe fn main_loop(worker: Worker<JobRef>, registry: Arc<Registry>, index: usiz
817
828
}
818
829
}
819
830
820
- let terminate_latch = registry. terminate . as_core_latch ( ) ;
831
+ let my_terminate_latch = & registry. thread_infos [ index ] . terminate ;
821
832
worker_thread. log ( || ThreadStart {
822
833
worker : index,
823
- terminate_addr : terminate_latch . addr ( ) ,
834
+ terminate_addr : my_terminate_latch . as_core_latch ( ) . addr ( ) ,
824
835
} ) ;
825
- worker_thread. wait_until_cold ( terminate_latch ) ;
836
+ worker_thread. wait_until ( my_terminate_latch ) ;
826
837
827
838
// Should not be any work left in our queue.
828
839
debug_assert ! ( worker_thread. take_local_job( ) . is_none( ) ) ;
0 commit comments