mirror of https://github.com/fatedier/frp.git
74 lines
1.4 KiB
Go
74 lines
1.4 KiB
Go
package broadcast
|
|
|
|
type Broadcast struct {
|
|
listeners []chan interface{}
|
|
reg chan (chan interface{})
|
|
unreg chan (chan interface{})
|
|
in chan interface{}
|
|
stop chan int64
|
|
stopStatus bool
|
|
}
|
|
|
|
func NewBroadcast() *Broadcast {
|
|
b := &Broadcast{
|
|
listeners: make([]chan interface{}, 0),
|
|
reg: make(chan (chan interface{})),
|
|
unreg: make(chan (chan interface{})),
|
|
in: make(chan interface{}),
|
|
stop: make(chan int64),
|
|
stopStatus: false,
|
|
}
|
|
|
|
go func() {
|
|
for {
|
|
select {
|
|
case l := <-b.unreg:
|
|
// remove L from b.listeners
|
|
// this operation is slow: O(n) but not used frequently
|
|
// unlike iterating over listeners
|
|
oldListeners := b.listeners
|
|
b.listeners = make([]chan interface{}, 0, len(oldListeners))
|
|
for _, oldL := range oldListeners {
|
|
if l != oldL {
|
|
b.listeners = append(b.listeners, oldL)
|
|
}
|
|
}
|
|
|
|
case l := <-b.reg:
|
|
b.listeners = append(b.listeners, l)
|
|
|
|
case item := <-b.in:
|
|
for _, l := range b.listeners {
|
|
l <- item
|
|
}
|
|
|
|
case _ = <-b.stop:
|
|
b.stopStatus = true
|
|
break
|
|
}
|
|
}
|
|
}()
|
|
|
|
return b
|
|
}
|
|
|
|
func (b *Broadcast) In() chan interface{} {
|
|
return b.in
|
|
}
|
|
|
|
func (b *Broadcast) Reg() chan interface{} {
|
|
listener := make(chan interface{})
|
|
b.reg <- listener
|
|
return listener
|
|
}
|
|
|
|
func (b *Broadcast) UnReg(listener chan interface{}) {
|
|
b.unreg <- listener
|
|
}
|
|
|
|
func (b *Broadcast) Close() {
|
|
if b.stopStatus == false {
|
|
b.stop <- 1
|
|
}
|
|
}
|