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  }