github.com/CAFxX/fastrand@v0.1.0/xoshiro256_sharded.go (about) 1 package fastrand 2 3 import ( 4 "runtime" 5 "sync" 6 "unsafe" 7 ) 8 9 // ShardedXoshiro256StarStar implements the Xoshiro256** PRNG with per-thread (per-P) states. 10 // 11 // This generator is safe for concurrent use by multiple goroutines. 12 // The zero value is not a valid state: use NewShardedXoshiro256StarStar to construct a valid instance. 13 // Increasing the value of GOMAXPROCS after instantiation will likely yield sub-optimal performance. 14 type ShardedXoshiro256StarStar struct { 15 states []paddedXoshiro256 16 fallbackMutex sync.Mutex 17 fallback Xoshiro256StarStar 18 } 19 20 type paddedXoshiro256 struct { 21 Xoshiro256StarStar 22 _ [cacheline - unsafe.Sizeof(Xoshiro256StarStar{})%cacheline]byte 23 } 24 25 // NewShardedXoshiro256StarStar creates a valid ShardedXoshiro256StarStar instance seeded using crypto/rand. 26 // 27 // Increasing the value of GOMAXPROCS after instantiation will likely yield sub-optimal performance. 28 func NewShardedXoshiro256StarStar() *ShardedXoshiro256StarStar { 29 r := &ShardedXoshiro256StarStar{} 30 r.states = make([]paddedXoshiro256, runtime.GOMAXPROCS(0)) 31 for i := range r.states { 32 r.states[i].Xoshiro256StarStar.safeSeed() 33 } 34 r.fallback.safeSeed() 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 *ShardedXoshiro256StarStar) 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 r.fallbackMutex.Lock() 48 n := r.fallback.Uint64() 49 r.fallbackMutex.Unlock() 50 return n 51 } 52 53 n := r.states[id].Uint64() 54 procUnpin() 55 return n 56 }