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