mirror of
https://github.com/golang/go
synced 2024-09-30 02:34:40 -06:00
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>
This commit is contained in:
parent
8dc08394f0
commit
7cf06f070e
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user