github.com/CAFxX/fastrand@v0.1.0/splitmix64_sharded.go (about) 1 package fastrand 2 3 import ( 4 "runtime" 5 "unsafe" 6 ) 7 8 const cacheline = 64 9 10 // ShardedSplitMix64 implements the Java 8 SplittableRandom generator with per-thread (per-P) states. 11 // 12 // This generator is safe for concurrent use by multiple goroutines. 13 // The zero value is a valid state, but it uses a static, all zero seed: use NewShardedSplitMix64 to instantiate a ShardedSplitMix64 with a random seed. 14 type ShardedSplitMix64 struct { 15 states []paddedSplitMix64 16 fallback AtomicSplitMix64 17 } 18 19 type paddedSplitMix64 struct { 20 SplitMix64 21 _ [cacheline - unsafe.Sizeof(SplitMix64{})%cacheline]byte 22 } 23 24 // NewShardedSplitMix64 creates a valid ShardedSplitMix64 instance seeded using crypto/rand. 25 // 26 // Increasing the value of GOMAXPROCS after instantiation will likely yield sub-optimal performance. 27 func NewShardedSplitMix64() *ShardedSplitMix64 { 28 r := &ShardedSplitMix64{ 29 states: make([]paddedSplitMix64, runtime.GOMAXPROCS(0)), 30 } 31 for i := range r.states { 32 r.states[i].Seed(Seed()) 33 } 34 r.fallback.Seed(Seed()) 35 return r 36 } 37 38 // Uint64 returns a random uint64. 39 // 40 // This function is safe for concurrent use by multiple goroutines. 41 func (r *ShardedSplitMix64) Uint64() uint64 { 42 l := len(r.states) // if r is nil, panic before procPin 43 id := procPin() 44 45 if fastrand_nounsafe || l <= id { 46 procUnpin() 47 return r.fallback.Uint64() 48 } 49 50 n := r.states[id].Uint64() 51 procUnpin() 52 return n 53 }