2020use crate :: owning_ref:: { Erased , OwningRef } ;
2121use std:: collections:: HashMap ;
2222use std:: hash:: { BuildHasher , Hash } ;
23+ use std:: mem:: MaybeUninit ;
2324use std:: ops:: { Deref , DerefMut } ;
2425use std:: panic:: { catch_unwind, resume_unwind, AssertUnwindSafe } ;
2526
@@ -30,6 +31,8 @@ pub use vec::AppendOnlyVec;
3031
3132mod vec;
3233
34+ static PARALLEL : std:: sync:: atomic:: AtomicBool = std:: sync:: atomic:: AtomicBool :: new ( false ) ;
35+
3336cfg_if ! {
3437 if #[ cfg( not( parallel_compiler) ) ] {
3538 pub auto trait Send { }
@@ -182,33 +185,6 @@ cfg_if! {
182185
183186 use std:: cell:: Cell ;
184187
185- #[ derive( Debug ) ]
186- pub struct WorkerLocal <T >( OneThread <T >) ;
187-
188- impl <T > WorkerLocal <T > {
189- /// Creates a new worker local where the `initial` closure computes the
190- /// value this worker local should take for each thread in the thread pool.
191- #[ inline]
192- pub fn new<F : FnMut ( usize ) -> T >( mut f: F ) -> WorkerLocal <T > {
193- WorkerLocal ( OneThread :: new( f( 0 ) ) )
194- }
195-
196- /// Returns the worker-local value for each thread
197- #[ inline]
198- pub fn into_inner( self ) -> Vec <T > {
199- vec![ OneThread :: into_inner( self . 0 ) ]
200- }
201- }
202-
203- impl <T > Deref for WorkerLocal <T > {
204- type Target = T ;
205-
206- #[ inline( always) ]
207- fn deref( & self ) -> & T {
208- & self . 0
209- }
210- }
211-
212188 pub type MTRef <' a, T > = & ' a mut T ;
213189
214190 #[ derive( Debug , Default ) ]
@@ -328,8 +304,6 @@ cfg_if! {
328304 } ;
329305 }
330306
331- pub use rayon_core:: WorkerLocal ;
332-
333307 pub use rayon:: iter:: ParallelIterator ;
334308 use rayon:: iter:: IntoParallelIterator ;
335309
@@ -364,6 +338,49 @@ cfg_if! {
364338 }
365339}
366340
341+ #[ derive( Debug ) ]
342+ pub struct WorkerLocal < T > {
343+ single_thread : bool ,
344+ inner : T ,
345+ mt_inner : Option < rayon_core:: WorkerLocal < T > > ,
346+ }
347+
348+ impl < T > WorkerLocal < T > {
349+ /// Creates a new worker local where the `initial` closure computes the
350+ /// value this worker local should take for each thread in the thread pool.
351+ #[ inline]
352+ pub fn new < F : FnMut ( usize ) -> T > ( mut f : F ) -> WorkerLocal < T > {
353+ if !PARALLEL . load ( Ordering :: Relaxed ) {
354+ WorkerLocal { single_thread : true , inner : f ( 0 ) , mt_inner : None }
355+ } else {
356+ // Safety: `inner` would never be accessed when multiple threads
357+ WorkerLocal {
358+ single_thread : false ,
359+ inner : unsafe { MaybeUninit :: uninit ( ) . assume_init ( ) } ,
360+ mt_inner : Some ( rayon_core:: WorkerLocal :: new ( f) ) ,
361+ }
362+ }
363+ }
364+
365+ /// Returns the worker-local value for each thread
366+ #[ inline]
367+ pub fn into_inner ( self ) -> Vec < T > {
368+ if self . single_thread { vec ! [ self . inner] } else { self . mt_inner . unwrap ( ) . into_inner ( ) }
369+ }
370+ }
371+
372+ impl < T > Deref for WorkerLocal < T > {
373+ type Target = T ;
374+
375+ #[ inline( always) ]
376+ fn deref ( & self ) -> & T {
377+ if self . single_thread { & self . inner } else { self . mt_inner . as_ref ( ) . unwrap ( ) . deref ( ) }
378+ }
379+ }
380+
381+ // Just for speed test
382+ unsafe impl < T : Send > std:: marker:: Sync for WorkerLocal < T > { }
383+
367384pub fn assert_sync < T : ?Sized + Sync > ( ) { }
368385pub fn assert_send < T : ?Sized + Send > ( ) { }
369386pub fn assert_send_val < T : ?Sized + Send > ( _t : & T ) { }
0 commit comments