@@ -10,7 +10,10 @@ use log::Event::*;
10
10
use sleep:: Sleep ;
11
11
use std:: any:: Any ;
12
12
use std:: cell:: Cell ;
13
+ use std:: collections:: hash_map:: DefaultHasher ;
14
+ use std:: hash:: Hasher ;
13
15
use std:: sync:: { Arc , Mutex , Once , ONCE_INIT } ;
16
+ use std:: sync:: atomic:: { AtomicUsize , ATOMIC_USIZE_INIT , Ordering } ;
14
17
use std:: thread;
15
18
use std:: mem;
16
19
use std:: usize;
@@ -601,7 +604,7 @@ impl WorkerThread {
601
604
return None ;
602
605
}
603
606
604
- let start = self . rng . next ( ) as usize % num_threads;
607
+ let start = self . rng . next_usize ( num_threads) ;
605
608
( start .. num_threads)
606
609
. chain ( 0 .. start)
607
610
. filter ( |& i| i != self . index )
@@ -716,12 +719,14 @@ struct XorShift64Star {
716
719
717
720
impl XorShift64Star {
718
721
fn new ( ) -> Self {
719
- // Any non-zero seed will do -- this uses a stack address, which should be unique since
720
- // we're only calling this once from each new thread. The address is also shift-XORed to
721
- // give us some high bits even on 32-bit platforms.
722
- let base = 0 ;
723
- let addr = & base as * const _ as u64 ;
724
- let seed = addr ^ ( addr << 32 ) ;
722
+ // Any non-zero seed will do -- this uses the hash of a global counter.
723
+ let mut seed = 0 ;
724
+ while seed == 0 {
725
+ let mut hasher = DefaultHasher :: new ( ) ;
726
+ static COUNTER : AtomicUsize = ATOMIC_USIZE_INIT ;
727
+ hasher. write_usize ( COUNTER . fetch_add ( 1 , Ordering :: Relaxed ) ) ;
728
+ seed = hasher. finish ( ) ;
729
+ }
725
730
726
731
XorShift64Star {
727
732
state : Cell :: new ( seed) ,
@@ -737,4 +742,9 @@ impl XorShift64Star {
737
742
self . state . set ( x) ;
738
743
x. wrapping_mul ( 0x2545_f491_4f6c_dd1d )
739
744
}
745
+
746
+ /// Return a value from `0..n`.
747
+ fn next_usize ( & self , n : usize ) -> usize {
748
+ ( self . next ( ) % n as u64 ) as usize
749
+ }
740
750
}
0 commit comments