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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: common/data/rand/mathrand/impl.go
diff --git a/common/data/rand/mathrand/impl.go b/common/data/rand/mathrand/impl.go
index cb0cda4b6e1307d414e7984192cd469d12d66ff8..bd514c424feb97a683fe7f347ed0035e2e1715cb 100644
--- a/common/data/rand/mathrand/impl.go
+++ b/common/data/rand/mathrand/impl.go
@@ -14,6 +14,10 @@ import (
// A Rand instance is not necessarily safe for concurrent use. In order to
// ensure that it is, wrap it in Locking or obtain it from a method that
// provides this guarantee (e.g., Get).
+//
+// All Rand functions MUST NOT PANIC. In particular, the Locking implementation
+// relies on embedded methods not panicking in order to release its lock, and
+// a panic will cause it to hold its lock indefinitely.
type Rand interface {
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64
// from the source in the context or the shared global source.
@@ -94,6 +98,10 @@ type Rand interface {
// for it. This can be used by callers to pull and use a *rand.Rand instance
// out of the Context safely.
//
+ // Other "mathrand" functions and objects MUST NOT BE USED inside the
+ // callback, as WithGoRand holds the lock to the current Rand instance, so any
+ // additional function call will deadlock.
+ //
// The callback's r must not be retained or used outside of hte scope of the
// callback.
WithGoRand(fn func(r *rand.Rand) error) error
@@ -121,88 +129,98 @@ func wrapLocking(r Rand) Rand {
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64
// from the source in the context or the shared global source.
-func (l *Locking) Int63() int64 {
+func (l *Locking) Int63() (v int64) {
l.Lock()
- defer l.Unlock()
- return l.R.Int63()
+ v = l.R.Int63()
+ l.Unlock()
+ return
}
// Uint32 returns a pseudo-random 32-bit value as a uint32 from the source in
// the context or the shared global source.
-func (l *Locking) Uint32() uint32 {
+func (l *Locking) Uint32() (v uint32) {
l.Lock()
- defer l.Unlock()
- return l.R.Uint32()
+ v = l.R.Uint32()
+ l.Unlock()
+ return
}
// Int31 returns a non-negative pseudo-random 31-bit integer as an int32 from
// the source in the context or the shared global source.
-func (l *Locking) Int31() int32 {
+func (l *Locking) Int31() (v int32) {
l.Lock()
- defer l.Unlock()
- return l.R.Int31()
+ v = l.R.Int31()
+ l.Unlock()
+ return
}
// Int returns a non-negative pseudo-random int from the source in the context
// or the shared global source.
-func (l *Locking) Int() int {
+func (l *Locking) Int() (v int) {
l.Lock()
- defer l.Unlock()
- return l.R.Int()
+ v = l.R.Int()
+ l.Unlock()
+ return
}
// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n)
// from the source in the context or the shared global source.
//
// It panics if n <= 0.
-func (l *Locking) Int63n(n int64) int64 {
+func (l *Locking) Int63n(n int64) (v int64) {
l.Lock()
- defer l.Unlock()
- return l.R.Int63n(n)
+ v = l.R.Int63n(n)
+ l.Unlock()
+ return
}
// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n)
// from the source in the context or the shared global source.
//
// It panics if n <= 0.
-func (l *Locking) Int31n(n int32) int32 {
+func (l *Locking) Int31n(n int32) (v int32) {
l.Lock()
- defer l.Unlock()
- return l.R.Int31n(n)
+ v = l.R.Int31n(n)
+ l.Unlock()
+ return
}
// Intn returns, as an int, a non-negative pseudo-random number in [0,n) from
// the source in the context or the shared global source.
//
// It panics if n <= 0.
-func (l *Locking) Intn(n int) int {
+func (l *Locking) Intn(n int) (v int) {
l.Lock()
- defer l.Unlock()
- return l.R.Intn(n)
+ v = l.R.Intn(n)
+ l.Unlock()
+ return
}
// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0) from
// the source in the context or the shared global source.
-func (l *Locking) Float64() float64 {
+func (l *Locking) Float64() (v float64) {
l.Lock()
- defer l.Unlock()
- return l.R.Float64()
+ v = l.R.Float64()
+ l.Unlock()
+ return
}
// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0) from
// the source in the context or the shared global source.
-func (l *Locking) Float32() float32 {
+func (l *Locking) Float32() (v float32) {
l.Lock()
- defer l.Unlock()
- return l.R.Float32()
+ v = l.R.Float32()
+ l.Unlock()
+ return
}
// Perm returns, as a slice of n ints, a pseudo-random permutation of the
// integers [0,n) from the source in the context or the shared global source.
-func (l *Locking) Perm(n int) []int {
+func (l *Locking) Perm(n int) (v []int) {
l.Lock()
- defer l.Unlock()
- return l.R.Perm(n)
+ v = l.R.Perm(n)
+ l.Unlock()
+ return
}
// Read generates len(p) random bytes from the source in the context or
@@ -210,8 +228,9 @@ func (l *Locking) Perm(n int) []int {
// and a nil error.
func (l *Locking) Read(p []byte) (n int, err error) {
l.Lock()
- defer l.Unlock()
- return l.R.Read(p)
+ n, err = l.R.Read(p)
+ l.Unlock()
+ return
}
// NormFloat64 returns a normally distributed float64 in the range
@@ -224,10 +243,11 @@ func (l *Locking) Read(p []byte) (n int, err error) {
//
// sample = NormFloat64(ctx) * desiredStdDev + desiredMean
//
-func (l *Locking) NormFloat64() float64 {
+func (l *Locking) NormFloat64() (v float64) {
l.Lock()
- defer l.Unlock()
- return l.R.NormFloat64()
+ v = l.R.NormFloat64()
+ l.Unlock()
+ return
}
// ExpFloat64 returns an exponentially distributed float64 in the range
@@ -240,17 +260,18 @@ func (l *Locking) NormFloat64() float64 {
//
// sample = ExpFloat64(ctx) / desiredRateParameter
//
-func (l *Locking) ExpFloat64() float64 {
+func (l *Locking) ExpFloat64() (v float64) {
l.Lock()
- defer l.Unlock()
- return l.R.ExpFloat64()
+ v = l.R.ExpFloat64()
+ l.Unlock()
+ return
}
// WithGoRand invokes the supplied "fn" while holding an exclusive lock
// for it. This can be used by callers to pull and use a *rand.Rand instance
// out of the Context safely.
//
-// The callback's r must not be retained or used outside of hte scope of the
+// The callback's r must not be retained or used outside of the scope of the
// callback.
func (l *Locking) WithGoRand(fn func(r *rand.Rand) error) error {
l.Lock()

Powered by Google App Engine
This is Rietveld 408576698