11use :: { ExitHandler , PanicHandler , StartHandler , ThreadPoolBuilder , ThreadPoolBuildError , ErrorKind } ;
2- use crossbeam_deque:: { Deque , Steal , Stealer } ;
2+ use crossbeam_deque:: { self as deque , Worker , Pop , Steal , Stealer } ;
33use job:: { JobRef , StackJob } ;
44#[ cfg( rayon_unstable) ]
55use job:: Job ;
@@ -46,7 +46,7 @@ pub struct Registry {
4646}
4747
4848struct RegistryState {
49- job_injector : Deque < JobRef > ,
49+ job_injector : Worker < JobRef > ,
5050}
5151
5252/// ////////////////////////////////////////////////////////////////////////
@@ -100,16 +100,21 @@ impl Registry {
100100 let n_threads = builder. get_num_threads ( ) ;
101101 let breadth_first = builder. get_breadth_first ( ) ;
102102
103- let inj_worker = Deque :: new ( ) ;
104- let inj_stealer = inj_worker. stealer ( ) ;
105- let workers: Vec < _ > = ( 0 ..n_threads)
106- . map ( |_| Deque :: new ( ) )
107- . collect ( ) ;
108- let stealers: Vec < _ > = workers. iter ( ) . map ( |d| d. stealer ( ) ) . collect ( ) ;
103+ let ( inj_worker, inj_stealer) = deque:: fifo ( ) ;
104+ let ( workers, stealers) = ( 0 ..n_threads)
105+ . fold (
106+ ( Vec :: with_capacity ( n_threads) , Vec :: with_capacity ( n_threads) ) ,
107+ |( mut workers, mut stealers) , _| {
108+ let ( worker, stealer) = deque:: fifo ( ) ;
109+ workers. push ( worker) ;
110+ stealers. push ( stealer) ;
111+
112+ ( workers, stealers)
113+ } ) ;
109114
110115 let registry = Arc :: new ( Registry {
111- thread_infos : stealers. into_iter ( )
112- . map ( |s| ThreadInfo :: new ( s) )
116+ thread_infos : stealers. iter ( )
117+ . map ( |s| ThreadInfo :: new ( s. clone ( ) ) )
113118 . collect ( ) ,
114119 state : Mutex :: new ( RegistryState :: new ( inj_worker) ) ,
115120 sleep : Sleep :: new ( ) ,
@@ -123,7 +128,7 @@ impl Registry {
123128 // If we return early or panic, make sure to terminate existing threads.
124129 let t1000 = Terminator ( & registry) ;
125130
126- for ( index, worker) in workers. into_iter ( ) . enumerate ( ) {
131+ for ( index, ( worker, stealer ) ) in workers. into_iter ( ) . zip ( stealers . into_iter ( ) ) . enumerate ( ) {
127132 let registry = registry. clone ( ) ;
128133 let mut b = thread:: Builder :: new ( ) ;
129134 if let Some ( name) = builder. get_thread_name ( index) {
@@ -132,7 +137,7 @@ impl Registry {
132137 if let Some ( stack_size) = builder. get_stack_size ( ) {
133138 b = b. stack_size ( stack_size) ;
134139 }
135- if let Err ( e) = b. spawn ( move || unsafe { main_loop ( worker, registry, index, breadth_first) } ) {
140+ if let Err ( e) = b. spawn ( move || unsafe { main_loop ( worker, stealer , registry, index, breadth_first) } ) {
136141 return Err ( ThreadPoolBuildError :: new ( ErrorKind :: IOError ( e) ) )
137142 }
138143 }
@@ -417,7 +422,7 @@ pub struct RegistryId {
417422}
418423
419424impl RegistryState {
420- pub fn new ( job_injector : Deque < JobRef > ) -> RegistryState {
425+ pub fn new ( job_injector : Worker < JobRef > ) -> RegistryState {
421426 RegistryState {
422427 job_injector : job_injector,
423428 }
@@ -453,7 +458,10 @@ impl ThreadInfo {
453458
454459pub struct WorkerThread {
455460 /// the "worker" half of our local deque
456- worker : Deque < JobRef > ,
461+ worker : Worker < JobRef > ,
462+
463+ /// a stealer to allow us to take jobs from the bottom of our deque
464+ stealer : Stealer < JobRef > ,
457465
458466 index : usize ,
459467
@@ -513,7 +521,7 @@ impl WorkerThread {
513521
514522 #[ inline]
515523 pub fn local_deque_is_empty ( & self ) -> bool {
516- self . worker . len ( ) == 0
524+ self . worker . is_empty ( )
517525 }
518526
519527 /// Attempts to obtain a "local" job -- typically this means
@@ -523,10 +531,16 @@ impl WorkerThread {
523531 #[ inline]
524532 pub unsafe fn take_local_job ( & self ) -> Option < JobRef > {
525533 if !self . breadth_first {
526- self . worker . pop ( )
534+ loop {
535+ match self . worker . pop ( ) {
536+ Pop :: Empty => return None ,
537+ Pop :: Data ( d) => return Some ( d) ,
538+ Pop :: Retry => { } ,
539+ }
540+ }
527541 } else {
528542 loop {
529- match self . worker . steal ( ) {
543+ match self . stealer . steal ( ) {
530544 Steal :: Empty => return None ,
531545 Steal :: Data ( d) => return Some ( d) ,
532546 Steal :: Retry => { } ,
@@ -596,7 +610,14 @@ impl WorkerThread {
596610 /// local work to do.
597611 unsafe fn steal ( & self ) -> Option < JobRef > {
598612 // we only steal when we don't have any work to do locally
599- debug_assert ! ( self . worker. pop( ) . is_none( ) ) ;
613+ let has_work = loop {
614+ match self . worker . pop ( ) {
615+ Pop :: Empty => break false ,
616+ Pop :: Data ( _) => break true ,
617+ Pop :: Retry => { } ,
618+ }
619+ } ;
620+ debug_assert ! ( !has_work) ;
600621
601622 // otherwise, try to steal
602623 let num_threads = self . registry . thread_infos . len ( ) ;
@@ -630,12 +651,14 @@ impl WorkerThread {
630651
631652/// ////////////////////////////////////////////////////////////////////////
632653
633- unsafe fn main_loop ( worker : Deque < JobRef > ,
654+ unsafe fn main_loop ( worker : Worker < JobRef > ,
655+ stealer : Stealer < JobRef > ,
634656 registry : Arc < Registry > ,
635657 index : usize ,
636658 breadth_first : bool ) {
637659 let worker_thread = WorkerThread {
638660 worker : worker,
661+ stealer : stealer,
639662 breadth_first : breadth_first,
640663 index : index,
641664 rng : XorShift64Star :: new ( ) ,
0 commit comments