...
1 package entrypoint
2
3 import (
4 "sync"
5 )
6
7
8
9
10
11
12
13 type Notifier struct {
14 cond *sync.Cond
15 autoNotify bool
16 changeCount int
17 notifyCount int
18 }
19
20
21 func NewNotifier() *Notifier {
22 return &Notifier{
23 cond: sync.NewCond(&sync.Mutex{}),
24 }
25 }
26
27
28
29 func (n *Notifier) Changed() {
30 callNotify := false
31 func() {
32 n.cond.L.Lock()
33 defer n.cond.L.Unlock()
34 n.changeCount += 1
35 if n.autoNotify {
36 callNotify = true
37 }
38 }()
39
40 if callNotify {
41 n.Notify()
42 }
43 }
44
45
46 func (n *Notifier) AutoNotify(enabled bool) {
47 func() {
48 n.cond.L.Lock()
49 defer n.cond.L.Unlock()
50 n.autoNotify = enabled
51 }()
52
53 if enabled {
54 n.Notify()
55 }
56 }
57
58
59 func (n *Notifier) Notify() {
60 n.cond.L.Lock()
61 defer n.cond.L.Unlock()
62 n.notifyCount = n.changeCount
63 n.cond.Broadcast()
64 }
65
66 type StopFunc func()
67
68
69
70
71 func (n *Notifier) Listen(onChange func()) StopFunc {
72 stopped := false
73 go func() {
74 n.cond.L.Lock()
75 defer n.cond.L.Unlock()
76 count := 0
77 for {
78 if stopped {
79 return
80 }
81 if count < n.notifyCount {
82 onChange()
83 count = n.notifyCount
84 }
85 n.cond.Wait()
86 }
87 }()
88
89 return func() {
90 n.cond.L.Lock()
91 defer n.cond.L.Unlock()
92 stopped = true
93 n.cond.Broadcast()
94 }
95 }
96
View as plain text