1
1
package delay
2
2
3
3
import (
4
+ "math/rand"
4
5
"sync"
5
6
"time"
6
7
)
7
8
9
+ var sharedRNG = rand .New (rand .NewSource (time .Now ().UnixNano ()))
10
+
8
11
// Delay makes it easy to add (threadsafe) configurable delays to other
9
12
// objects.
10
13
type D interface {
@@ -23,8 +26,6 @@ type delay struct {
23
26
t time.Duration
24
27
}
25
28
26
- // TODO func Variable(time.Duration) D returns a delay with probablistic latency
27
-
28
29
func (d * delay ) Set (t time.Duration ) time.Duration {
29
30
d .l .Lock ()
30
31
defer d .l .Unlock ()
@@ -44,3 +45,61 @@ func (d *delay) Get() time.Duration {
44
45
defer d .l .Unlock ()
45
46
return d .t
46
47
}
48
+
49
+ // VariableNormal is a delay following a normal distribution
50
+ // Notice that to implement the D interface Set can only change the mean delay
51
+ // the standard deviation is set only at initialization
52
+ func VariableNormal (t , std time.Duration , rng * rand.Rand ) D {
53
+ if rng == nil {
54
+ rng = sharedRNG
55
+ }
56
+
57
+ v := & variableNormal {
58
+ std : std ,
59
+ rng : rng ,
60
+ }
61
+ v .t = t
62
+ return v
63
+ }
64
+
65
+ type variableNormal struct {
66
+ delay
67
+ std time.Duration
68
+ rng * rand.Rand
69
+ }
70
+
71
+ func (d * variableNormal ) Wait () {
72
+ d .l .RLock ()
73
+ defer d .l .RUnlock ()
74
+ randomDelay := time .Duration (d .rng .NormFloat64 () * float64 (d .std ))
75
+ time .Sleep (randomDelay + d .t )
76
+ }
77
+
78
+ // VariableUniform is a delay following a uniform distribution
79
+ // Notice that to implement the D interface Set can only change the minimum delay
80
+ // the delta is set only at initialization
81
+ func VariableUniform (t , d time.Duration , rng * rand.Rand ) D {
82
+ if rng == nil {
83
+ rng = sharedRNG
84
+ }
85
+
86
+ v := & variableUniform {
87
+ d : d ,
88
+ rng : rng ,
89
+ }
90
+ v .t = t
91
+ return v
92
+ }
93
+
94
+ type variableUniform struct {
95
+ delay
96
+ d time.Duration // max delta
97
+ rng * rand.Rand
98
+ }
99
+
100
+ func (d * variableUniform ) Wait () {
101
+ d .l .RLock ()
102
+ defer d .l .RUnlock ()
103
+ randomDelay := time .Duration (d .rng .Float64 () * float64 (d .d ))
104
+ time .Sleep (randomDelay + d .t )
105
+ }
0 commit comments