forked from Mxmilu666/frp
Add package "broadcast" for transmitting message to goroutines at the same time
This commit is contained in:
73
utils/broadcast/broadcast.go
Normal file
73
utils/broadcast/broadcast.go
Normal file
@@ -0,0 +1,73 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user