-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathtimer.go
More file actions
94 lines (85 loc) · 2.19 KB
/
timer.go
File metadata and controls
94 lines (85 loc) · 2.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package timer
import "time"
type State int
const (
stateIdle State = iota
stateActive
stateExpired
)
// The Timer type represents a single event. When the Timer expires,
// the current time will be sent on C, unless the Timer was created by AfterFunc.
// A Timer must be created with NewTimer or AfterFunc.
type Timer struct {
C <-chan time.Time
c chan time.Time
duration time.Duration
state State
fn func()
startedAt time.Time
t *time.Timer
}
// AfterFunc waits after calling its Start method for the duration
// to elapse and then calls f in its own goroutine.
// It returns a Timer that can be used to cancel the call using its Stop method,
// or pause using its Pause method
func AfterFunc(d time.Duration, f func()) *Timer {
t := new(Timer)
t.duration = d
t.fn = func() {
t.state = stateExpired
f()
}
return t
}
// NewTimer creates a new Timer.
// It returns a Timer that can be used to cancel the call using its Stop method,
// or pause using its Pause method
func NewTimer(d time.Duration) *Timer {
c := make(chan time.Time, 1)
t := new(Timer)
t.C = c
t.c = c
t.duration = d
t.fn = func() {
t.state = stateExpired
t.c <- time.Now()
}
return t
}
// Pause pauses current timer until Start method will be called.
// Next Start call will wait rest of duration.
func (t *Timer) Pause() bool {
if t.state != stateActive {
return false
}
if !t.t.Stop() {
t.state = stateExpired
return false
}
t.state = stateIdle
dur := time.Since(t.startedAt)
t.duration = t.duration - dur
return true
}
// Start starts Timer that will send the current time on its channel after at least duration d.
func (t *Timer) Start() bool {
if t.state != stateIdle {
return false
}
t.startedAt = time.Now()
t.state = stateActive
t.t = time.AfterFunc(t.duration, t.fn)
return true
}
// Stop prevents the Timer from firing. It returns true if the call stops the timer,
// false if the timer has already expired or been stopped.
// Stop does not close the channel, to prevent a read from the channel succeeding incorrectly.
func (t *Timer) Stop() bool {
if t.state != stateActive {
return false
}
t.startedAt = time.Now()
t.state = stateExpired
t.t.Stop()
return true
}