blob: e7e1d400102131af3890b5bcbb846897eb39a476 [file] [log] [blame]
Abhay Kumara2ae5992025-11-10 14:02:24 +00001package clockwork
2
3import "time"
4
5// Timer provides an interface which can be used instead of directly using
6// [time.Timer]. The real-time timer t provides events through t.C which becomes
7// t.Chan() to make this channel requirement definable in this interface.
8type Timer interface {
9 Chan() <-chan time.Time
10 Reset(d time.Duration) bool
11 Stop() bool
12}
13
14type realTimer struct{ *time.Timer }
15
16func (r realTimer) Chan() <-chan time.Time {
17 return r.C
18}
19
20type fakeTimer struct {
21 // The channel associated with the firer, used to send expiration times.
22 c chan time.Time
23
24 // The time when the firer expires. Only meaningful if the firer is currently
25 // one of a FakeClock's waiters.
26 exp time.Time
27
28 // reset and stop provide the implementation of the respective exported
29 // functions.
30 reset func(d time.Duration) bool
31 stop func() bool
32
33 // If present when the timer fires, the timer calls afterFunc in its own
34 // goroutine rather than sending the time on Chan().
35 afterFunc func()
36}
37
38func newFakeTimer(fc *FakeClock, afterfunc func()) *fakeTimer {
39 var ft *fakeTimer
40 ft = &fakeTimer{
41 c: make(chan time.Time, 1),
42 reset: func(d time.Duration) bool {
43 fc.l.Lock()
44 defer fc.l.Unlock()
45 // fc.l must be held across the calls to stopExpirer & setExpirer.
46 stopped := fc.stopExpirer(ft)
47 fc.setExpirer(ft, d)
48 return stopped
49 },
50 stop: func() bool { return fc.stop(ft) },
51
52 afterFunc: afterfunc,
53 }
54 return ft
55}
56
57func (f *fakeTimer) Chan() <-chan time.Time { return f.c }
58
59func (f *fakeTimer) Reset(d time.Duration) bool { return f.reset(d) }
60
61func (f *fakeTimer) Stop() bool { return f.stop() }
62
63func (f *fakeTimer) expire(now time.Time) *time.Duration {
64 if f.afterFunc != nil {
65 go f.afterFunc()
66 return nil
67 }
68
69 // Never block on expiration.
70 select {
71 case f.c <- now:
72 default:
73 }
74 return nil
75}
76
77func (f *fakeTimer) expiration() time.Time { return f.exp }
78
79func (f *fakeTimer) setExpiration(t time.Time) { f.exp = t }