1package rand 2 3import ( 4 "math/rand" 5 "sync" 6) 7 8// LockedRand implements NumberGenerator and embeds Rand that is safe for concurrent use. 9type LockedRand struct { 10 lk sync.Mutex 11 r *rand.Rand 12} 13 14// NewLockedRand creates a new LockedRand that implements all Rand functions that is safe 15// for concurrent use. 16func NewLockedRand(seed int64) *LockedRand { 17 return &LockedRand{ 18 r: rand.New(rand.NewSource(seed)), 19 } 20} 21 22// Seed uses the provided seed value to initialize the generator to a deterministic state. 23// Seed should not be called concurrently with any other Rand method. 24func (lr *LockedRand) Seed(seed int64) { 25 lr.lk.Lock() 26 lr.r.Seed(seed) 27 lr.lk.Unlock() 28} 29 30// TwoInt63 generates 2 random int64 without locking twice. 31func (lr *LockedRand) TwoInt63() (n1, n2 int64) { 32 lr.lk.Lock() 33 n1 = lr.r.Int63() 34 n2 = lr.r.Int63() 35 lr.lk.Unlock() 36 return 37} 38 39// Int63 returns a non-negative pseudo-random 63-bit integer as an int64. 40func (lr *LockedRand) Int63() (n int64) { 41 lr.lk.Lock() 42 n = lr.r.Int63() 43 lr.lk.Unlock() 44 return 45} 46 47// Uint32 returns a pseudo-random 32-bit value as a uint32. 48func (lr *LockedRand) Uint32() (n uint32) { 49 lr.lk.Lock() 50 n = lr.r.Uint32() 51 lr.lk.Unlock() 52 return 53} 54 55// Uint64 returns a pseudo-random 64-bit value as a uint64. 56func (lr *LockedRand) Uint64() (n uint64) { 57 lr.lk.Lock() 58 n = lr.r.Uint64() 59 lr.lk.Unlock() 60 return 61} 62 63// TwoUint64 generates 2 random uint64 without locking twice. 64func (lr *LockedRand) TwoUint64() (n1, n2 uint64) { 65 lr.lk.Lock() 66 n1 = lr.r.Uint64() 67 n2 = lr.r.Uint64() 68 lr.lk.Unlock() 69 return 70} 71 72// Int31 returns a non-negative pseudo-random 31-bit integer as an int32. 73func (lr *LockedRand) Int31() (n int32) { 74 lr.lk.Lock() 75 n = lr.r.Int31() 76 lr.lk.Unlock() 77 return 78} 79 80// Int returns a non-negative pseudo-random int. 81func (lr *LockedRand) Int() (n int) { 82 lr.lk.Lock() 83 n = lr.r.Int() 84 lr.lk.Unlock() 85 return 86} 87 88// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n). 89// It panics if n <= 0. 90func (lr *LockedRand) Int63n(n int64) (r int64) { 91 lr.lk.Lock() 92 r = lr.r.Int63n(n) 93 lr.lk.Unlock() 94 return 95} 96 97// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n). 98// It panics if n <= 0. 99func (lr *LockedRand) Int31n(n int32) (r int32) { 100 lr.lk.Lock() 101 r = lr.r.Int31n(n) 102 lr.lk.Unlock() 103 return 104} 105 106// Intn returns, as an int, a non-negative pseudo-random number in [0,n). 107// It panics if n <= 0. 108func (lr *LockedRand) Intn(n int) (r int) { 109 lr.lk.Lock() 110 r = lr.r.Intn(n) 111 lr.lk.Unlock() 112 return 113} 114 115// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0). 116func (lr *LockedRand) Float64() (n float64) { 117 lr.lk.Lock() 118 n = lr.r.Float64() 119 lr.lk.Unlock() 120 return 121} 122 123// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0). 124func (lr *LockedRand) Float32() (n float32) { 125 lr.lk.Lock() 126 n = lr.r.Float32() 127 lr.lk.Unlock() 128 return 129} 130 131// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n). 132func (lr *LockedRand) Perm(n int) (r []int) { 133 lr.lk.Lock() 134 r = lr.r.Perm(n) 135 lr.lk.Unlock() 136 return 137} 138 139// Read generates len(p) random bytes and writes them into p. It 140// always returns len(p) and a nil error. 141// Read should not be called concurrently with any other Rand method. 142func (lr *LockedRand) Read(p []byte) (n int, err error) { 143 lr.lk.Lock() 144 n, err = lr.r.Read(p) 145 lr.lk.Unlock() 146 return 147} 148