Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: common/data/rand/mathrand/impl.go

Issue 2588213002: Use global rand.Rand instance in mathrand. (Closed)
Patch Set: Better comment. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The LUCI Authors. All rights reserved. 1 // Copyright 2016 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 package mathrand 5 package mathrand
6 6
7 import ( 7 import (
8 "math/rand" 8 "math/rand"
9 "sync" 9 "sync"
10 ) 10 )
11 11
12 // Rand is a random number generator interface. 12 // Rand is a random number generator interface.
13 // 13 //
14 // A Rand instance is not necessarily safe for concurrent use. In order to 14 // A Rand instance is not necessarily safe for concurrent use. In order to
15 // ensure that it is, wrap it in Locking or obtain it from a method that 15 // ensure that it is, wrap it in Locking or obtain it from a method that
16 // provides this guarantee (e.g., Get). 16 // provides this guarantee (e.g., Get).
17 //
18 // All Rand functions MUST NOT PANIC. In particular, the Locking implementation
19 // relies on embedded methods not panicking in order to release its lock, and
20 // a panic will cause it to hold its lock indefinitely.
17 type Rand interface { 21 type Rand interface {
18 // Int63 returns a non-negative pseudo-random 63-bit integer as an int64 22 // Int63 returns a non-negative pseudo-random 63-bit integer as an int64
19 // from the source in the context or the shared global source. 23 // from the source in the context or the shared global source.
20 Int63() int64 24 Int63() int64
21 25
22 // Uint32 returns a pseudo-random 32-bit value as a uint32 from the sour ce in 26 // Uint32 returns a pseudo-random 32-bit value as a uint32 from the sour ce in
23 // the context or the shared global source. 27 // the context or the shared global source.
24 Uint32() uint32 28 Uint32() uint32
25 29
26 // Int31 returns a non-negative pseudo-random 31-bit integer as an int32 from 30 // Int31 returns a non-negative pseudo-random 31-bit integer as an int32 from
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 // the output using: 91 // the output using:
88 // 92 //
89 // sample = ExpFloat64(ctx) / desiredRateParameter 93 // sample = ExpFloat64(ctx) / desiredRateParameter
90 // 94 //
91 ExpFloat64() float64 95 ExpFloat64() float64
92 96
93 // WithGoRand invokes the supplied "fn" while holding an exclusive lock 97 // WithGoRand invokes the supplied "fn" while holding an exclusive lock
94 // for it. This can be used by callers to pull and use a *rand.Rand inst ance 98 // for it. This can be used by callers to pull and use a *rand.Rand inst ance
95 // out of the Context safely. 99 // out of the Context safely.
96 // 100 //
101 // Other "mathrand" functions and objects MUST NOT BE USED inside the
102 // callback, as WithGoRand holds the lock to the current Rand instance, so any
103 // additional function call will deadlock.
104 //
97 // The callback's r must not be retained or used outside of hte scope of the 105 // The callback's r must not be retained or used outside of hte scope of the
98 // callback. 106 // callback.
99 WithGoRand(fn func(r *rand.Rand) error) error 107 WithGoRand(fn func(r *rand.Rand) error) error
100 } 108 }
101 109
102 // Locking wraps a Rand instance in a layer that locks around all of its 110 // Locking wraps a Rand instance in a layer that locks around all of its
103 // methods. 111 // methods.
104 // 112 //
105 // A user must hold Locking's Mutex if the want to directly access and use 113 // A user must hold Locking's Mutex if the want to directly access and use
106 // Locking's R member safely. 114 // Locking's R member safely.
107 // 115 //
108 // By default, a Rand instance is not safe for concurrent use. A ocking Rand 116 // By default, a Rand instance is not safe for concurrent use. A ocking Rand
109 // instance is. 117 // instance is.
110 type Locking struct { 118 type Locking struct {
111 sync.Mutex 119 sync.Mutex
112 R Rand 120 R Rand
113 } 121 }
114 122
115 func wrapLocking(r Rand) Rand { 123 func wrapLocking(r Rand) Rand {
116 if _, ok := r.(*Locking); ok { 124 if _, ok := r.(*Locking); ok {
117 return r 125 return r
118 } 126 }
119 return &Locking{R: r} 127 return &Locking{R: r}
120 } 128 }
121 129
122 // Int63 returns a non-negative pseudo-random 63-bit integer as an int64 130 // Int63 returns a non-negative pseudo-random 63-bit integer as an int64
123 // from the source in the context or the shared global source. 131 // from the source in the context or the shared global source.
124 func (l *Locking) Int63() int64 { 132 func (l *Locking) Int63() (v int64) {
125 l.Lock() 133 l.Lock()
126 » defer l.Unlock() 134 » v = l.R.Int63()
127 » return l.R.Int63() 135 » l.Unlock()
136 » return
128 } 137 }
129 138
130 // Uint32 returns a pseudo-random 32-bit value as a uint32 from the source in 139 // Uint32 returns a pseudo-random 32-bit value as a uint32 from the source in
131 // the context or the shared global source. 140 // the context or the shared global source.
132 func (l *Locking) Uint32() uint32 { 141 func (l *Locking) Uint32() (v uint32) {
133 l.Lock() 142 l.Lock()
134 » defer l.Unlock() 143 » v = l.R.Uint32()
135 » return l.R.Uint32() 144 » l.Unlock()
145 » return
136 } 146 }
137 147
138 // Int31 returns a non-negative pseudo-random 31-bit integer as an int32 from 148 // Int31 returns a non-negative pseudo-random 31-bit integer as an int32 from
139 // the source in the context or the shared global source. 149 // the source in the context or the shared global source.
140 func (l *Locking) Int31() int32 { 150 func (l *Locking) Int31() (v int32) {
141 l.Lock() 151 l.Lock()
142 » defer l.Unlock() 152 » v = l.R.Int31()
143 » return l.R.Int31() 153 » l.Unlock()
154 » return
144 } 155 }
145 156
146 // Int returns a non-negative pseudo-random int from the source in the context 157 // Int returns a non-negative pseudo-random int from the source in the context
147 // or the shared global source. 158 // or the shared global source.
148 func (l *Locking) Int() int { 159 func (l *Locking) Int() (v int) {
149 l.Lock() 160 l.Lock()
150 » defer l.Unlock() 161 » v = l.R.Int()
151 » return l.R.Int() 162 » l.Unlock()
163 » return
152 } 164 }
153 165
154 // Int63n returns, as an int64, a non-negative pseudo-random number in [0,n) 166 // Int63n returns, as an int64, a non-negative pseudo-random number in [0,n)
155 // from the source in the context or the shared global source. 167 // from the source in the context or the shared global source.
156 // 168 //
157 // It panics if n <= 0. 169 // It panics if n <= 0.
158 func (l *Locking) Int63n(n int64) int64 { 170 func (l *Locking) Int63n(n int64) (v int64) {
159 l.Lock() 171 l.Lock()
160 » defer l.Unlock() 172 » v = l.R.Int63n(n)
161 » return l.R.Int63n(n) 173 » l.Unlock()
174 » return
162 } 175 }
163 176
164 // Int31n returns, as an int32, a non-negative pseudo-random number in [0,n) 177 // Int31n returns, as an int32, a non-negative pseudo-random number in [0,n)
165 // from the source in the context or the shared global source. 178 // from the source in the context or the shared global source.
166 // 179 //
167 // It panics if n <= 0. 180 // It panics if n <= 0.
168 func (l *Locking) Int31n(n int32) int32 { 181 func (l *Locking) Int31n(n int32) (v int32) {
169 l.Lock() 182 l.Lock()
170 » defer l.Unlock() 183 » v = l.R.Int31n(n)
171 » return l.R.Int31n(n) 184 » l.Unlock()
185 » return
172 } 186 }
173 187
174 // Intn returns, as an int, a non-negative pseudo-random number in [0,n) from 188 // Intn returns, as an int, a non-negative pseudo-random number in [0,n) from
175 // the source in the context or the shared global source. 189 // the source in the context or the shared global source.
176 // 190 //
177 // It panics if n <= 0. 191 // It panics if n <= 0.
178 func (l *Locking) Intn(n int) int { 192 func (l *Locking) Intn(n int) (v int) {
179 l.Lock() 193 l.Lock()
180 » defer l.Unlock() 194 » v = l.R.Intn(n)
181 » return l.R.Intn(n) 195 » l.Unlock()
196 » return
182 } 197 }
183 198
184 // Float64 returns, as a float64, a pseudo-random number in [0.0,1.0) from 199 // Float64 returns, as a float64, a pseudo-random number in [0.0,1.0) from
185 // the source in the context or the shared global source. 200 // the source in the context or the shared global source.
186 func (l *Locking) Float64() float64 { 201 func (l *Locking) Float64() (v float64) {
187 l.Lock() 202 l.Lock()
188 » defer l.Unlock() 203 » v = l.R.Float64()
189 » return l.R.Float64() 204 » l.Unlock()
205 » return
190 } 206 }
191 207
192 // Float32 returns, as a float32, a pseudo-random number in [0.0,1.0) from 208 // Float32 returns, as a float32, a pseudo-random number in [0.0,1.0) from
193 // the source in the context or the shared global source. 209 // the source in the context or the shared global source.
194 func (l *Locking) Float32() float32 { 210 func (l *Locking) Float32() (v float32) {
195 l.Lock() 211 l.Lock()
196 » defer l.Unlock() 212 » v = l.R.Float32()
197 » return l.R.Float32() 213 » l.Unlock()
214 » return
198 } 215 }
199 216
200 // Perm returns, as a slice of n ints, a pseudo-random permutation of the 217 // Perm returns, as a slice of n ints, a pseudo-random permutation of the
201 // integers [0,n) from the source in the context or the shared global source. 218 // integers [0,n) from the source in the context or the shared global source.
202 func (l *Locking) Perm(n int) []int { 219 func (l *Locking) Perm(n int) (v []int) {
203 l.Lock() 220 l.Lock()
204 » defer l.Unlock() 221 » v = l.R.Perm(n)
205 » return l.R.Perm(n) 222 » l.Unlock()
223 » return
206 } 224 }
207 225
208 // Read generates len(p) random bytes from the source in the context or 226 // Read generates len(p) random bytes from the source in the context or
209 // the shared global source and writes them into p. It always returns len(p) 227 // the shared global source and writes them into p. It always returns len(p)
210 // and a nil error. 228 // and a nil error.
211 func (l *Locking) Read(p []byte) (n int, err error) { 229 func (l *Locking) Read(p []byte) (n int, err error) {
212 l.Lock() 230 l.Lock()
213 » defer l.Unlock() 231 » n, err = l.R.Read(p)
214 » return l.R.Read(p) 232 » l.Unlock()
233 » return
215 } 234 }
216 235
217 // NormFloat64 returns a normally distributed float64 in the range 236 // NormFloat64 returns a normally distributed float64 in the range
218 // [-math.MaxFloat64, +math.MaxFloat64] with standard normal distribution 237 // [-math.MaxFloat64, +math.MaxFloat64] with standard normal distribution
219 // (mean = 0, stddev = 1) from the source in the context or the shared global 238 // (mean = 0, stddev = 1) from the source in the context or the shared global
220 // source. 239 // source.
221 // 240 //
222 // To produce a different normal distribution, callers can adjust the output 241 // To produce a different normal distribution, callers can adjust the output
223 // using: 242 // using:
224 // 243 //
225 // sample = NormFloat64(ctx) * desiredStdDev + desiredMean 244 // sample = NormFloat64(ctx) * desiredStdDev + desiredMean
226 // 245 //
227 func (l *Locking) NormFloat64() float64 { 246 func (l *Locking) NormFloat64() (v float64) {
228 l.Lock() 247 l.Lock()
229 » defer l.Unlock() 248 » v = l.R.NormFloat64()
230 » return l.R.NormFloat64() 249 » l.Unlock()
250 » return
231 } 251 }
232 252
233 // ExpFloat64 returns an exponentially distributed float64 in the range 253 // ExpFloat64 returns an exponentially distributed float64 in the range
234 // (0, +math.MaxFloat64] with an exponential distribution whose rate parameter 254 // (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
235 // (lambda) is 1 and whose mean is 1/lambda (1) from the source in the context 255 // (lambda) is 1 and whose mean is 1/lambda (1) from the source in the context
236 // or the shared global source. 256 // or the shared global source.
237 // 257 //
238 // To produce a distribution with a different rate parameter, callers can adjust 258 // To produce a distribution with a different rate parameter, callers can adjust
239 // the output using: 259 // the output using:
240 // 260 //
241 // sample = ExpFloat64(ctx) / desiredRateParameter 261 // sample = ExpFloat64(ctx) / desiredRateParameter
242 // 262 //
243 func (l *Locking) ExpFloat64() float64 { 263 func (l *Locking) ExpFloat64() (v float64) {
244 l.Lock() 264 l.Lock()
245 » defer l.Unlock() 265 » v = l.R.ExpFloat64()
246 » return l.R.ExpFloat64() 266 » l.Unlock()
267 » return
247 } 268 }
248 269
249 // WithGoRand invokes the supplied "fn" while holding an exclusive lock 270 // WithGoRand invokes the supplied "fn" while holding an exclusive lock
250 // for it. This can be used by callers to pull and use a *rand.Rand instance 271 // for it. This can be used by callers to pull and use a *rand.Rand instance
251 // out of the Context safely. 272 // out of the Context safely.
252 // 273 //
253 // The callback's r must not be retained or used outside of hte scope of the 274 // The callback's r must not be retained or used outside of the scope of the
254 // callback. 275 // callback.
255 func (l *Locking) WithGoRand(fn func(r *rand.Rand) error) error { 276 func (l *Locking) WithGoRand(fn func(r *rand.Rand) error) error {
256 l.Lock() 277 l.Lock()
257 defer l.Unlock() 278 defer l.Unlock()
258 return l.R.WithGoRand(fn) 279 return l.R.WithGoRand(fn)
259 } 280 }
260 281
261 // wrapped is a simple wrapper to a *math.Rand instance. 282 // wrapped is a simple wrapper to a *math.Rand instance.
262 type wrapped struct { 283 type wrapped struct {
263 *rand.Rand 284 *rand.Rand
264 } 285 }
265 286
266 // Wrap wraps a Rand instance, allowing it to satisfy the Rand interface. 287 // Wrap wraps a Rand instance, allowing it to satisfy the Rand interface.
267 func wrapRand(r *rand.Rand) Rand { return wrapped{r} } 288 func wrapRand(r *rand.Rand) Rand { return wrapped{r} }
268 289
269 func (w wrapped) WithGoRand(fn func(r *rand.Rand) error) error { return fn(w.Ran d) } 290 func (w wrapped) WithGoRand(fn func(r *rand.Rand) error) error { return fn(w.Ran d) }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698