-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathxoshiro256_sharded.go
56 lines (49 loc) · 1.56 KB
/
xoshiro256_sharded.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package fastrand
import (
"runtime"
"sync"
"unsafe"
)
// ShardedXoshiro256StarStar implements the Xoshiro256** PRNG with per-thread (per-P) states.
//
// This generator is safe for concurrent use by multiple goroutines.
// The zero value is not a valid state: use NewShardedXoshiro256StarStar to construct a valid instance.
// Increasing the value of GOMAXPROCS after instantiation will likely yield sub-optimal performance.
type ShardedXoshiro256StarStar struct {
states []paddedXoshiro256
fallbackMutex sync.Mutex
fallback Xoshiro256StarStar
}
type paddedXoshiro256 struct {
Xoshiro256StarStar
_ [cacheline - unsafe.Sizeof(Xoshiro256StarStar{})%cacheline]byte
}
// NewShardedXoshiro256StarStar creates a valid ShardedXoshiro256StarStar instance seeded using crypto/rand.
//
// Increasing the value of GOMAXPROCS after instantiation will likely yield sub-optimal performance.
func NewShardedXoshiro256StarStar() *ShardedXoshiro256StarStar {
r := &ShardedXoshiro256StarStar{}
r.states = make([]paddedXoshiro256, runtime.GOMAXPROCS(0))
for i := range r.states {
r.states[i].Xoshiro256StarStar.safeSeed()
}
r.fallback.safeSeed()
return r
}
// Uint64 returns a random uint64.
//
// This function is safe for concurrent use by multiple goroutines.
func (r *ShardedXoshiro256StarStar) Uint64() uint64 {
l := len(r.states) // if r is nil, panic before procPin
id := procPin()
if fastrand_nounsafe || l <= id {
procUnpin()
r.fallbackMutex.Lock()
n := r.fallback.Uint64()
r.fallbackMutex.Unlock()
return n
}
n := r.states[id].Uint64()
procUnpin()
return n
}