forked from stellar-deprecated/horizon
/
main.go
83 lines (72 loc) · 1.39 KB
/
main.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
package pump
import (
"time"
)
// Pump represents a broadcast channel that, when triggered via the input
// channel, triggers all channels created through the `Subscribe()` method.
type Pump struct {
trigger <-chan struct{}
outputs map[chan struct{}]bool
adds chan chan struct{}
removes chan chan struct{}
}
func NewPump(trigger <-chan struct{}) *Pump {
result := &Pump{
trigger: trigger,
outputs: map[chan struct{}]bool{},
adds: make(chan chan struct{}, 10),
removes: make(chan chan struct{}, 10),
}
go result.run()
return result
}
func Tick(d time.Duration) chan struct{} {
result := make(chan struct{})
tick := time.Tick(d)
go func() {
for {
<-tick
result <- struct{}{}
}
}()
return result
}
func (p *Pump) Subscribe() chan struct{} {
result := make(chan struct{}, 1)
p.adds <- result
return result
}
func (p *Pump) Unsubscribe(l chan struct{}) {
p.removes <- l
}
func (p *Pump) run() {
for {
select {
case _, more := <-p.trigger:
if !more {
for o, _ := range p.outputs {
close(o)
}
return
}
for o, _ := range p.outputs {
trySend(o)
}
case ch := <-p.adds:
p.outputs[ch] = true
case ch := <-p.removes:
close(ch)
delete(p.outputs, ch)
}
}
}
// try to trigger the provided channel, but don't bother
// if you can't.
func trySend(o chan struct{}) {
select {
case o <- struct{}{}:
//NOOP
default:
//NOOP
}
}