aboutsummaryrefslogtreecommitdiff
path: root/src/math
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2022-10-04 11:24:47 -0400
committerGopher Robot <gobot@golang.org>2022-10-18 14:49:46 +0000
commit7cf06f070e56dfb6507122704bc75d697ccc350f (patch)
treee696b248b098d6347c7ba127c6b8adbbe6af8f24 /src/math
parent8dc08394f0d5f83523080e4dd99fded26b7c1ceb (diff)
downloadgo-7cf06f070e56dfb6507122704bc75d697ccc350f.tar.xz
math/rand: refactor to delay allocation of global source
This sets up for delaying the decision of which seed to use, but this CL still keeps the original global Seed(1) semantics. Preparation for #54880. Change-Id: Ibfa9d50ec9023aa755a83852e55168fa7d24b115 Reviewed-on: https://go-review.googlesource.com/c/go/+/443057 Auto-Submit: Russ Cox <rsc@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/math')
-rw-r--r--src/math/rand/rand.go42
1 files changed, 29 insertions, 13 deletions
diff --git a/src/math/rand/rand.go b/src/math/rand/rand.go
index bcf2f9c950..4627d4515f 100644
--- a/src/math/rand/rand.go
+++ b/src/math/rand/rand.go
@@ -42,10 +42,10 @@ type Source64 interface {
// safe for concurrent use by multiple goroutines.
// The returned Source implements Source64.
func NewSource(seed int64) Source {
- return newSource64(seed)
+ return newSource(seed)
}
-func newSource64(seed int64) Source64 {
+func newSource(seed int64) *rngSource {
var rng rngSource
rng.Seed(seed)
return &rng
@@ -295,10 +295,7 @@ func read(p []byte, src Source, readVal *int64, readPos *int8) (n int, err error
* Top-level convenience functions
*/
-var globalRand = New(&lockedSource{src: NewSource(1).(*rngSource)})
-
-// Type assert that globalRand's source is a lockedSource whose src is a *rngSource.
-var _ *rngSource = globalRand.src.(*lockedSource).src
+var globalRand = New(new(lockedSource))
// Seed uses the provided seed value to initialize the default Source to a
// deterministic state. If Seed is not called, the generator behaves as
@@ -383,42 +380,61 @@ func NormFloat64() float64 { return globalRand.NormFloat64() }
func ExpFloat64() float64 { return globalRand.ExpFloat64() }
type lockedSource struct {
- lk sync.Mutex
- src *rngSource
+ lk sync.Mutex
+ s *rngSource // nil if not yet allocated
+}
+
+// source returns r.s, allocating and seeding it if needed.
+// The caller must have locked r.
+func (r *lockedSource) source() *rngSource {
+ if r.s == nil {
+ r.s = newSource(1)
+ }
+ return r.s
}
func (r *lockedSource) Int63() (n int64) {
r.lk.Lock()
- n = r.src.Int63()
+ n = r.source().Int63()
r.lk.Unlock()
return
}
func (r *lockedSource) Uint64() (n uint64) {
r.lk.Lock()
- n = r.src.Uint64()
+ n = r.source().Uint64()
r.lk.Unlock()
return
}
func (r *lockedSource) Seed(seed int64) {
r.lk.Lock()
- r.src.Seed(seed)
+ r.seed(seed)
r.lk.Unlock()
}
// seedPos implements Seed for a lockedSource without a race condition.
func (r *lockedSource) seedPos(seed int64, readPos *int8) {
r.lk.Lock()
- r.src.Seed(seed)
+ r.seed(seed)
*readPos = 0
r.lk.Unlock()
}
+// seed seeds the underlying source.
+// The caller must have locked r.lk.
+func (r *lockedSource) seed(seed int64) {
+ if r.s == nil {
+ r.s = newSource(seed)
+ } else {
+ r.s.Seed(seed)
+ }
+}
+
// read implements Read for a lockedSource without a race condition.
func (r *lockedSource) read(p []byte, readVal *int64, readPos *int8) (n int, err error) {
r.lk.Lock()
- n, err = read(p, r.src, readVal, readPos)
+ n, err = read(p, r.source(), readVal, readPos)
r.lk.Unlock()
return
}