| 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()
|
|
|