50 lines
910 B
Go
50 lines
910 B
Go
package tracer
|
|
|
|
import (
|
|
cryptorand "crypto/rand"
|
|
"log"
|
|
"math"
|
|
"math/big"
|
|
"math/rand"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// random holds a thread-safe source of random numbers.
|
|
var random *rand.Rand
|
|
|
|
func init() {
|
|
var seed int64
|
|
n, err := cryptorand.Int(cryptorand.Reader, big.NewInt(math.MaxInt64))
|
|
if err == nil {
|
|
seed = n.Int64()
|
|
} else {
|
|
log.Printf("%scannot generate random seed: %v; using current time\n", errorPrefix, err)
|
|
seed = time.Now().UnixNano()
|
|
}
|
|
random = rand.New(&safeSource{
|
|
source: rand.NewSource(seed),
|
|
})
|
|
}
|
|
|
|
// safeSource holds a thread-safe implementation of rand.Source64.
|
|
type safeSource struct {
|
|
source rand.Source
|
|
sync.Mutex
|
|
}
|
|
|
|
func (rs *safeSource) Int63() int64 {
|
|
rs.Lock()
|
|
n := rs.source.Int63()
|
|
rs.Unlock()
|
|
|
|
return n
|
|
}
|
|
|
|
func (rs *safeSource) Uint64() uint64 { return uint64(rs.Int63()) }
|
|
|
|
func (rs *safeSource) Seed(seed int64) {
|
|
rs.Lock()
|
|
rs.Seed(seed)
|
|
rs.Unlock()
|
|
}
|