github.com/leanovate/gopter@v0.2.9/locked_source.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 // Taken from golang lockedSource implementation https://github.com/golang/go/blob/master/src/math/rand/rand.go#L371-L410 5 6 package gopter 7 8 import ( 9 "math/rand" 10 "sync" 11 ) 12 13 type lockedSource struct { 14 lk sync.Mutex 15 src rand.Source64 16 } 17 18 // NewLockedSource takes a seed and returns a new 19 // lockedSource for use with rand.New 20 func NewLockedSource(seed int64) *lockedSource { 21 return &lockedSource{ 22 src: rand.NewSource(seed).(rand.Source64), 23 } 24 } 25 26 func (r *lockedSource) Int63() (n int64) { 27 r.lk.Lock() 28 n = r.src.Int63() 29 r.lk.Unlock() 30 return 31 } 32 33 func (r *lockedSource) Uint64() (n uint64) { 34 r.lk.Lock() 35 n = r.src.Uint64() 36 r.lk.Unlock() 37 return 38 } 39 40 func (r *lockedSource) Seed(seed int64) { 41 r.lk.Lock() 42 r.src.Seed(seed) 43 r.lk.Unlock() 44 } 45 46 // seedPos implements Seed for a lockedSource without a race condition. 47 func (r *lockedSource) seedPos(seed int64, readPos *int8) { 48 r.lk.Lock() 49 r.src.Seed(seed) 50 *readPos = 0 51 r.lk.Unlock() 52 } 53 54 // read implements Read for a lockedSource without a race condition. 55 func (r *lockedSource) read(p []byte, readVal *int64, readPos *int8) (n int, err error) { 56 r.lk.Lock() 57 n, err = read(p, r.src.Int63, readVal, readPos) 58 r.lk.Unlock() 59 return 60 } 61 62 func read(p []byte, int63 func() int64, readVal *int64, readPos *int8) (n int, err error) { 63 pos := *readPos 64 val := *readVal 65 for n = 0; n < len(p); n++ { 66 if pos == 0 { 67 val = int63() 68 pos = 7 69 } 70 p[n] = byte(val) 71 val >>= 8 72 pos-- 73 } 74 *readPos = pos 75 *readVal = val 76 return 77 }