@@ -34,33 +34,39 @@ func (ft *fakeTicker) Stop() {
34
34
ft .stop <- true
35
35
}
36
36
37
- // tick sends the tick time to the ticker channel after every period.
38
- // Tick events are discarded if the underlying ticker channel does
39
- // not have enough capacity.
40
- func (ft * fakeTicker ) tick () {
41
- tick := ft .clock .Now ()
42
- for {
43
- tick = tick .Add (ft .period )
44
- remaining := tick .Sub (ft .clock .Now ())
45
- if remaining <= 0 {
46
- // The tick should have already happened. This can happen when
47
- // Advance() is called on the fake clock with a duration larger
48
- // than this ticker's period.
37
+ // runTickThread initializes a background goroutine to send the tick time to the ticker channel
38
+ // after every period. Tick events are discarded if the underlying ticker channel does not have
39
+ // enough capacity.
40
+ func (ft * fakeTicker ) runTickThread () {
41
+ nextTick := ft .clock .Now ().Add (ft .period )
42
+ next := ft .clock .After (ft .period )
43
+ go func () {
44
+ for {
49
45
select {
50
- case ft .c <- tick :
51
- default :
46
+ case <- ft .stop :
47
+ return
48
+ case <- next :
49
+ // We send the time that the tick was supposed to occur at.
50
+ tick := nextTick
51
+ // Before sending the tick, we'll compute the next tick time and star the clock.After call.
52
+ now := ft .clock .Now ()
53
+ // First, figure out how many periods there have been between "now" and the time we were
54
+ // supposed to have trigged, then advance over all of those.
55
+ skipTicks := (now .Sub (tick ) + ft .period - 1 ) / ft .period
56
+ nextTick = nextTick .Add (skipTicks * ft .period )
57
+ // Now, keep advancing until we are past now. This should happen at most once.
58
+ for ! nextTick .After (now ) {
59
+ nextTick = nextTick .Add (ft .period )
60
+ }
61
+ // Figure out how long between now and the next scheduled tick, then wait that long.
62
+ remaining := nextTick .Sub (now )
63
+ next = ft .clock .After (remaining )
64
+ // Finally, we can actually send the tick.
65
+ select {
66
+ case ft .c <- tick :
67
+ default :
68
+ }
52
69
}
53
- continue
54
70
}
55
-
56
- select {
57
- case <- ft .stop :
58
- return
59
- case <- ft .clock .After (remaining ):
60
- select {
61
- case ft .c <- tick :
62
- default :
63
- }
64
- }
65
- }
71
+ }()
66
72
}
0 commit comments