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  }