mirror of
https://github.com/mjl-/mox.git
synced 2024-12-26 16:33:47 +03:00
8550a5af45
the current Intn calls in queue could be called concurrently, found by the race detector with upcoming new tests. best to just prevent any possible concurrent access.
48 lines
937 B
Go
48 lines
937 B
Go
package mox
|
|
|
|
import (
|
|
cryptorand "crypto/rand"
|
|
"encoding/binary"
|
|
"fmt"
|
|
mathrand "math/rand"
|
|
"sync"
|
|
)
|
|
|
|
type rand struct {
|
|
rand *mathrand.Rand
|
|
sync.Mutex
|
|
}
|
|
|
|
// NewPseudoRand returns a new PRNG seeded with random bytes from crypto/rand. Its
|
|
// functions can be called concurrently.
|
|
func NewPseudoRand() *rand {
|
|
return &rand{rand: mathrand.New(mathrand.NewSource(CryptoRandInt()))}
|
|
}
|
|
|
|
func (r *rand) Float64() float64 {
|
|
r.Lock()
|
|
defer r.Unlock()
|
|
return r.rand.Float64()
|
|
}
|
|
|
|
func (r *rand) Intn(n int) int {
|
|
r.Lock()
|
|
defer r.Unlock()
|
|
return r.rand.Intn(n)
|
|
}
|
|
|
|
func (r *rand) Read(buf []byte) (int, error) {
|
|
r.Lock()
|
|
defer r.Unlock()
|
|
return r.rand.Read(buf)
|
|
}
|
|
|
|
// CryptoRandInt returns a cryptographically random number.
|
|
func CryptoRandInt() int64 {
|
|
buf := make([]byte, 8)
|
|
_, err := cryptorand.Read(buf)
|
|
if err != nil {
|
|
panic(fmt.Errorf("reading random bytes: %v", err))
|
|
}
|
|
return int64(binary.LittleEndian.Uint64(buf))
|
|
}
|