forked from gomatcha/matcha
/
ticker.go
109 lines (91 loc) · 1.64 KB
/
ticker.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package internal
import (
"sync"
"time"
"gomatcha.io/matcha/bridge"
"gomatcha.io/matcha/comm"
)
var tickers = struct {
ts map[int]*Ticker
mu *sync.Mutex
maxKey int
}{
ts: map[int]*Ticker{},
mu: &sync.Mutex{},
maxKey: 0,
}
func init() {
bridge.RegisterFunc("gomatcha.io/matcha/animate screenUpdate", screenUpdate)
}
func screenUpdate() {
tickers.mu.Lock()
ts := []*Ticker{}
for _, i := range tickers.ts {
ts = append(ts, i)
}
tickers.mu.Unlock()
for _, i := range ts {
i.Signal()
}
}
type Ticker struct {
key int
mu sync.Mutex
funcs map[comm.Id]func()
maxId comm.Id
timer *time.Timer
start time.Time
duration time.Duration
}
func NewTicker(duration time.Duration) *Ticker {
tickers.mu.Lock()
defer tickers.mu.Unlock()
tickers.maxKey += 1
t := &Ticker{
key: tickers.maxKey,
funcs: map[comm.Id]func(){},
start: time.Now(),
duration: duration,
}
t.timer = time.AfterFunc(duration, func() {
t.Stop()
})
tickers.ts[t.key] = t
return t
}
func (t *Ticker) Notify(f func()) comm.Id {
t.mu.Lock()
defer t.mu.Unlock()
t.maxId += 1
t.funcs[t.maxId] = f
return t.maxId
}
func (t *Ticker) Unnotify(key comm.Id) {
t.mu.Lock()
defer t.mu.Unlock()
delete(t.funcs, key)
}
func (t *Ticker) Value() float64 {
v := float64(time.Since(t.start)) / float64(t.duration)
if v < 0 {
v = 0
} else if v > 1 {
v = 1
}
return v
}
func (t *Ticker) Stop() {
tickers.mu.Lock()
defer tickers.mu.Unlock()
t.mu.Lock()
defer t.mu.Unlock()
delete(tickers.ts, t.key)
}
func (t *Ticker) Signal() {
t.mu.Lock()
funcs := t.funcs
t.mu.Unlock()
for _, f := range funcs {
f()
}
}