@@ -647,6 +647,7 @@ thread_local! {
647647/// Workers have one core memory-safety guarantee: Any jobs added to the worker
648648/// will eventually be executed.
649649pub struct Worker {
650+ pub ( crate ) migrated : Cell < bool > ,
650651 pub ( crate ) lease : Lease ,
651652 pub ( crate ) queue : JobQueue ,
652653}
@@ -736,6 +737,7 @@ impl Worker {
736737 // problem that the same thread can occupy multiple workers on the same
737738 // thread. We many eventually need to design something to prevent this.
738739 let worker = Worker {
740+ migrated : Cell :: new ( false ) ,
739741 lease,
740742 queue : JobQueue :: new ( ) ,
741743 } ;
@@ -749,7 +751,7 @@ impl Worker {
749751
750752 // Execute the work queue until it's empty
751753 while let Some ( job_ref) = worker. queue . pop_front ( ) {
752- job_ref . execute ( & worker ) ;
754+ worker . execute ( job_ref , false ) ;
753755 }
754756
755757 // Swap back to pointing to the previous value (possibly null).
@@ -762,6 +764,10 @@ impl Worker {
762764 result
763765 }
764766
767+ pub fn index ( & self ) -> usize {
768+ self . lease . index
769+ }
770+
765771 /// Tries to promote the oldest job in the local stack to a shared job. If
766772 /// the local job queue is empty, or if the shared queue is full, this does
767773 /// nothing. If the promotion is successful, it tries to wake another
@@ -814,12 +820,15 @@ impl Worker {
814820
815821 /// Tries to find a job to execute, either in the local queue or shared on
816822 /// the threadpool.
823+ ///
824+ /// The second value is true if the job was shared, or false if it was spawned locally.
817825 #[ inline]
818- pub fn find_work ( & self ) -> Option < JobRef > {
826+ pub fn find_work ( & self ) -> Option < ( JobRef , bool ) > {
819827 // We give preference first to things in our local deque, then in other
820828 // workers deques, and finally to injected jobs from the outside. The
821829 // idea is to finish what we started before we take on something new.
822- self . queue . pop_back ( ) . or_else ( || self . claim_shared_job ( ) )
830+ self . queue . pop_back ( ) . map ( |job| ( job, false ) )
831+ . or_else ( || self . claim_shared_job ( ) . map ( |job| ( job, true ) ) )
823832 }
824833
825834 /// Claims a shared job from the thread pool.
@@ -842,7 +851,7 @@ impl Worker {
842851 pub fn yield_local ( & self ) -> Yield {
843852 match self . queue . pop_back ( ) {
844853 Some ( job_ref) => {
845- job_ref . execute ( self ) ;
854+ self . execute ( job_ref , false ) ;
846855 Yield :: Executed
847856 }
848857 None => Yield :: Idle ,
@@ -860,13 +869,29 @@ impl Worker {
860869 #[ inline]
861870 pub fn yield_now ( & self ) -> Yield {
862871 match self . find_work ( ) {
863- Some ( job_ref) => {
864- job_ref . execute ( self ) ;
872+ Some ( ( job_ref, migrated ) ) => {
873+ self . execute ( job_ref , migrated ) ;
865874 Yield :: Executed
866875 }
867876 None => Yield :: Idle ,
868877 }
869878 }
879+
880+ /// Returns `true` if the current job is executing on a different thread
881+ /// from the one on which it was created. Returns `false` if not executing a
882+ /// job, or if the current job was created on the current thread.
883+ #[ inline]
884+ pub fn migrated ( & self ) -> bool {
885+ self . migrated . get ( )
886+ }
887+
888+ /// Executes a job on a worker
889+ #[ inline]
890+ pub fn execute ( & self , job_ref : JobRef , migrated : bool ) {
891+ let migrated = self . migrated . replace ( migrated) ;
892+ job_ref. execute ( self ) ;
893+ self . migrated . set ( migrated) ;
894+ }
870895}
871896
872897// -----------------------------------------------------------------------------
@@ -1063,7 +1088,7 @@ impl Worker {
10631088
10641089 // Even if it's not the droid we were looking for, we must still
10651090 // execute the job.
1066- job . execute ( self ) ;
1091+ self . execute ( job , false ) ;
10671092 }
10681093
10691094 // Wait for the job to complete, then return the result.
@@ -1217,7 +1242,7 @@ fn managed_worker(lease: Lease, halt: Arc<AtomicBool>, barrier: Arc<Barrier>) {
12171242 Worker :: occupy ( lease, |worker| {
12181243 while !halt. load ( Ordering :: Relaxed ) {
12191244 if let Some ( job) = worker. queue . pop_back ( ) {
1220- job . execute ( worker ) ;
1245+ worker . execute ( job , false ) ;
12211246 continue ;
12221247 }
12231248
@@ -1226,7 +1251,7 @@ fn managed_worker(lease: Lease, halt: Arc<AtomicBool>, barrier: Arc<Barrier>) {
12261251 while !halt. load ( Ordering :: Relaxed ) {
12271252 if let Some ( job) = state. claim_shared_job ( ) {
12281253 drop ( state) ;
1229- job . execute ( worker ) ;
1254+ worker . execute ( job , true ) ;
12301255 break ;
12311256 }
12321257
0 commit comments