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

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

Issue 2588213002: Use global rand.Rand instance in mathrand. (Closed)
Patch Set: 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
« no previous file with comments | « common/data/rand/mathrand/impl.go ('k') | common/data/rand/mathrand/mathrand_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The LUCI Authors. All rights reserved. 1 // Copyright 2015 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 implements a mockable interface for math/rand.Rand. 5 // Package mathrand implements a mockable interface for math/rand.Rand.
6 // 6 //
7 // It is controllable through context.Context. You should use this instead of 7 // It is controllable through context.Context. You should use this instead of
8 // math/rand directly, to allow you to make deterministic tests. 8 // math/rand directly, to allow you to make deterministic tests.
9 package mathrand 9 package mathrand
10 10
11 import ( 11 import (
12 "math/rand" 12 "math/rand"
13 13
14 "golang.org/x/net/context" 14 "golang.org/x/net/context"
15 ) 15 )
16 16
17 var key = "holds a rand.Rand for mathrand" 17 var key = "holds a rand.Rand for mathrand"
18 18
19 // globalRand is a global mathrand.Rand instance that is backed by a math/rand
20 // instance. It is locking, and is safe for return as a default.
21 var (
22 // globalRandBase is the NON-LOCKING global *rand.Rand instance.
23 globalRandBase = wrapped{newRand()}
24
25 // globalRand is a Locking wrapper around globalRandBase. globalRandBase MUST
26 // not be used without holding this lock.
27 globalRand = &Locking{R: globalRandBase}
28 )
29
19 func newRand() *rand.Rand { 30 func newRand() *rand.Rand {
20 return rand.New(rand.NewSource(rand.Int63())) 31 return rand.New(rand.NewSource(rand.Int63()))
21 } 32 }
22 33
23 func getRand(c context.Context) Rand { 34 func getRand(c context.Context) Rand {
24 if r, ok := c.Value(&key).(Rand); ok { 35 if r, ok := c.Value(&key).(Rand); ok {
25 return r 36 return r
26 } 37 }
27 return nil 38 return nil
28 } 39 }
29 40
30 // Get gets a Rand from the Context. The resulting Rand is safe for concurrent 41 // Get gets a Rand from the Context. The resulting Rand is safe for concurrent
31 // use. 42 // use.
32 // 43 //
33 // If one hasn't been set, this creates a new Rand object with a Source 44 // If one hasn't been set, this creates a new Rand object with a Source
34 // initialized from the global randomness source provided by stdlib. 45 // initialized from the global randomness source provided by stdlib.
35 // 46 //
36 // If you want to get just a single random number, prefer to use a corresponding 47 // If you want to get just a single random number, prefer to use a corresponding
37 // global function instead: they know how to use math/rand global RNG directly 48 // global function instead: they know how to use math/rand global RNG directly
38 // and thus are much faster in case the context doesn't have a rand.Rand 49 // and thus are much faster in case the context doesn't have a rand.Rand
39 // installed. 50 // installed.
40 // 51 //
41 // Use 'Get' only if you plan to obtain a large series of random numbers. 52 // Use 'Get' only if you plan to obtain a large series of random numbers.
42 func Get(c context.Context) Rand { 53 func Get(c context.Context) Rand {
43 if r := getRand(c); r != nil { 54 if r := getRand(c); r != nil {
44 return r 55 return r
45 } 56 }
46 57
47 // Generate a new Rand instance and return it. Our callers expect this t o be 58 // Generate a new Rand instance and return it. Our callers expect this t o be
Vadim Sh. 2016/12/20 01:40:38 this comment is stale now
dnj 2016/12/20 02:16:12 Done.
48 // concurrency-safe. 59 // concurrency-safe.
49 » return wrapLocking(wrapRand(newRand())) 60 » return globalRand
50 } 61 }
51 62
52 // Set sets the current *"math/rand".Rand object in the context. 63 // Set sets the current *"math/rand".Rand object in the context.
53 // 64 //
54 // Useful for testing with a quick mock. The supplied *rand.Rand will be wrapped 65 // Useful for testing with a quick mock. The supplied *rand.Rand will be wrapped
55 // in a *Locking if necessary such that when it is returned from Get, it is 66 // in a *Locking if necessary such that when it is returned from Get, it is
56 // safe for concurrent use. 67 // safe for concurrent use.
57 func Set(c context.Context, mr *rand.Rand) context.Context { 68 func Set(c context.Context, mr *rand.Rand) context.Context {
58 var r Rand 69 var r Rand
59 if mr != nil { 70 if mr != nil {
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 if r := getRand(c); r != nil { 238 if r := getRand(c); r != nil {
228 return r.ExpFloat64() 239 return r.ExpFloat64()
229 } 240 }
230 return rand.ExpFloat64() 241 return rand.ExpFloat64()
231 } 242 }
232 243
233 // WithGoRand invokes the supplied "fn" while holding an exclusive lock 244 // WithGoRand invokes the supplied "fn" while holding an exclusive lock
234 // for it. This can be used by callers to pull and use a *rand.Rand instance 245 // for it. This can be used by callers to pull and use a *rand.Rand instance
235 // out of the Context safely. 246 // out of the Context safely.
236 // 247 //
237 // The callback's r must not be retained or used outside of hte scope of the 248 // The callback's r must not be retained or used outside of hte scope of the
Vadim Sh. 2016/12/20 01:40:38 typo: hte scope
dnj 2016/12/20 02:16:12 Done.
238 // callback. 249 // callback.
239 func WithGoRand(c context.Context, fn func(r *rand.Rand) error) error { 250 func WithGoRand(c context.Context, fn func(r *rand.Rand) error) error {
240 if r := getRand(c); r != nil { 251 if r := getRand(c); r != nil {
241 return r.WithGoRand(fn) 252 return r.WithGoRand(fn)
242 } 253 }
243 254
244 » // No Rand is installed in our Context. Generate a single-use Rand insta nce. 255 » // Return our globalRandBase. We MUST hold globalRand's lock in order fo r this
245 » // We don't need to wrap this at all, since the premise of this method i s 256 » // to be safe.
246 » // that the result is not safe for concurrent use. 257 » globalRand.Lock()
247 » return fn(newRand()) 258 » defer globalRand.Unlock()
259 » return fn(globalRandBase.Rand)
248 } 260 }
OLDNEW
« no previous file with comments | « common/data/rand/mathrand/impl.go ('k') | common/data/rand/mathrand/mathrand_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698