This repository has been archived by the owner on Oct 25, 2018. It is now read-only.
/
timer.go
91 lines (84 loc) · 2.1 KB
/
timer.go
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
package exchange
import (
"github.com/inconshreveable/log15"
"math/rand"
"strconv"
"time"
)
type Timer struct {
C chan time.Time
stop chan struct{}
pause chan struct{}
resume chan struct{}
startedat time.Time
pausedat time.Time
remaining time.Duration
finished bool
number uint64
}
func (t *Timer) Stop() {
if t.finished {
panic("Stop on finished timer. n=" + strconv.FormatUint(t.number, 10))
}
t.stop <- struct{}{}
}
func (t *Timer) Pause() {
if t.finished {
panic("Pause on finished timer. n=" + strconv.FormatUint(t.number, 10))
}
t.pause <- struct{}{}
}
func (t *Timer) Resume() {
if t.finished {
panic("Resume on finished timer. n=" + strconv.FormatUint(t.number, 10))
}
t.resume <- struct{}{}
}
func (t *Timer) runTimer() {
log15.Info("Timer started", "number", t.number, "remaining", t.remaining)
tt := time.NewTimer(t.remaining)
for {
select {
case <-t.stop:
log15.Info("Stopping timer", "number", t.number, "remaining", t.remaining)
t.finished = true
close(t.C)
return
case <-t.pause:
log15.Info("Pausing timer", "number", t.number, "remaining", t.remaining)
t.pausedat = time.Now()
t.remaining -= t.pausedat.Sub(t.startedat)
tt.Stop()
case <-t.resume:
t.startedat = time.Now()
elapsed := t.startedat.Sub(t.pausedat)
if elapsed > t.remaining {
log15.Info("Timer completed (b)", "number", t.number, "remaining", t.remaining)
t.C <- time.Now().Add(-t.remaining)
t.finished = true
return
}
log15.Info("Resuming timer", "number", t.number, "remaining", t.remaining, "elapsed", elapsed)
tt = time.NewTimer(t.remaining - elapsed)
t.remaining -= elapsed
case ttt := <-tt.C:
log15.Info("Timer completed", "number", t.number, "remaining", t.remaining)
t.C <- ttt
t.finished = true
return
}
}
}
func NewTimer(tt time.Duration) *Timer {
t := &Timer{
C: make(chan time.Time, 1),
stop: make(chan struct{}),
pause: make(chan struct{}),
resume: make(chan struct{}),
startedat: time.Now(),
remaining: tt,
number: uint64(rand.Uint32()),
}
go t.runTimer()
return t
}