mirror of
https://gitee.com/IrisVega/frp.git
synced 2024-11-01 22:31:29 +08:00
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
|
||
|
}
|
||
|
}
|