Chromium Code Reviews| Index: common/data/rand/mathrand/mathrand.go |
| diff --git a/common/data/rand/mathrand/mathrand.go b/common/data/rand/mathrand/mathrand.go |
| index 58b48efbb418f80f5d26849655f072537549ded9..cc521ffe4171bfd49779b9e524d0534ae85adc24 100644 |
| --- a/common/data/rand/mathrand/mathrand.go |
| +++ b/common/data/rand/mathrand/mathrand.go |
| @@ -16,6 +16,17 @@ import ( |
| var key = "holds a rand.Rand for mathrand" |
| +// globalRand is a global mathrand.Rand instance that is backed by a math/rand |
| +// instance. It is locking, and is safe for return as a default. |
| +var ( |
| + // globalRandBase is the NON-LOCKING global *rand.Rand instance. |
| + globalRandBase = wrapped{newRand()} |
| + |
| + // globalRand is a Locking wrapper around globalRandBase. globalRandBase MUST |
| + // not be used without holding this lock. |
| + globalRand = &Locking{R: globalRandBase} |
| +) |
| + |
| func newRand() *rand.Rand { |
| return rand.New(rand.NewSource(rand.Int63())) |
| } |
| @@ -46,7 +57,7 @@ func Get(c context.Context) Rand { |
| // Generate a new Rand instance and return it. Our callers expect this to be |
|
Vadim Sh.
2016/12/20 01:40:38
this comment is stale now
dnj
2016/12/20 02:16:12
Done.
|
| // concurrency-safe. |
| - return wrapLocking(wrapRand(newRand())) |
| + return globalRand |
| } |
| // Set sets the current *"math/rand".Rand object in the context. |
| @@ -241,8 +252,9 @@ func WithGoRand(c context.Context, fn func(r *rand.Rand) error) error { |
| return r.WithGoRand(fn) |
| } |
| - // No Rand is installed in our Context. Generate a single-use Rand instance. |
| - // We don't need to wrap this at all, since the premise of this method is |
| - // that the result is not safe for concurrent use. |
| - return fn(newRand()) |
| + // Return our globalRandBase. We MUST hold globalRand's lock in order for this |
| + // to be safe. |
| + globalRand.Lock() |
| + defer globalRand.Unlock() |
| + return fn(globalRandBase.Rand) |
| } |