2020-08-26 13:27:00 -07:00
|
|
|
package melody
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
2024-08-27 10:04:05 -07:00
|
|
|
"sync/atomic"
|
2020-08-26 13:27:00 -07:00
|
|
|
)
|
|
|
|
|
2024-08-27 10:04:05 -07:00
|
|
|
type sessionSet struct {
|
|
|
|
mu sync.RWMutex
|
|
|
|
members map[*Session]struct{}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ss *sessionSet) add(s *Session) {
|
|
|
|
ss.mu.Lock()
|
|
|
|
defer ss.mu.Unlock()
|
|
|
|
|
|
|
|
ss.members[s] = struct{}{}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ss *sessionSet) del(s *Session) {
|
|
|
|
ss.mu.Lock()
|
|
|
|
defer ss.mu.Unlock()
|
|
|
|
|
|
|
|
delete(ss.members, s)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ss *sessionSet) clear() {
|
|
|
|
ss.mu.Lock()
|
|
|
|
defer ss.mu.Unlock()
|
|
|
|
|
|
|
|
ss.members = make(map[*Session]struct{})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ss *sessionSet) each(cb func(*Session)) {
|
|
|
|
ss.mu.RLock()
|
|
|
|
defer ss.mu.RUnlock()
|
|
|
|
|
|
|
|
for s := range ss.members {
|
|
|
|
cb(s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ss *sessionSet) len() int {
|
|
|
|
ss.mu.RLock()
|
|
|
|
defer ss.mu.RUnlock()
|
|
|
|
|
|
|
|
return len(ss.members)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ss *sessionSet) all() []*Session {
|
|
|
|
ss.mu.RLock()
|
|
|
|
defer ss.mu.RUnlock()
|
|
|
|
|
|
|
|
s := make([]*Session, 0, len(ss.members))
|
|
|
|
for k := range ss.members {
|
|
|
|
s = append(s, k)
|
|
|
|
}
|
|
|
|
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2020-08-26 13:27:00 -07:00
|
|
|
type hub struct {
|
2024-08-27 10:04:05 -07:00
|
|
|
sessions sessionSet
|
|
|
|
broadcast chan envelope
|
2020-08-26 13:27:00 -07:00
|
|
|
register chan *Session
|
|
|
|
unregister chan *Session
|
2024-08-27 10:04:05 -07:00
|
|
|
exit chan envelope
|
|
|
|
open atomic.Bool
|
2020-08-26 13:27:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func newHub() *hub {
|
|
|
|
return &hub{
|
2024-08-27 10:04:05 -07:00
|
|
|
sessions: sessionSet{
|
|
|
|
members: make(map[*Session]struct{}),
|
|
|
|
},
|
|
|
|
broadcast: make(chan envelope),
|
2020-08-26 13:27:00 -07:00
|
|
|
register: make(chan *Session),
|
|
|
|
unregister: make(chan *Session),
|
2024-08-27 10:04:05 -07:00
|
|
|
exit: make(chan envelope),
|
2020-08-26 13:27:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *hub) run() {
|
2024-08-27 10:04:05 -07:00
|
|
|
h.open.Store(true)
|
|
|
|
|
2020-08-26 13:27:00 -07:00
|
|
|
loop:
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case s := <-h.register:
|
2024-08-27 10:04:05 -07:00
|
|
|
h.sessions.add(s)
|
2020-08-26 13:27:00 -07:00
|
|
|
case s := <-h.unregister:
|
2024-08-27 10:04:05 -07:00
|
|
|
h.sessions.del(s)
|
2020-08-26 13:27:00 -07:00
|
|
|
case m := <-h.broadcast:
|
2024-08-27 10:04:05 -07:00
|
|
|
h.sessions.each(func(s *Session) {
|
|
|
|
if m.filter == nil {
|
|
|
|
s.writeMessage(m)
|
|
|
|
} else if m.filter(s) {
|
2020-08-26 13:27:00 -07:00
|
|
|
s.writeMessage(m)
|
|
|
|
}
|
2024-08-27 10:04:05 -07:00
|
|
|
})
|
2020-08-26 13:27:00 -07:00
|
|
|
case m := <-h.exit:
|
2024-08-27 10:04:05 -07:00
|
|
|
h.open.Store(false)
|
|
|
|
|
|
|
|
h.sessions.each(func(s *Session) {
|
2020-08-26 13:27:00 -07:00
|
|
|
s.writeMessage(m)
|
|
|
|
s.Close()
|
2024-08-27 10:04:05 -07:00
|
|
|
})
|
|
|
|
|
|
|
|
h.sessions.clear()
|
|
|
|
|
2020-08-26 13:27:00 -07:00
|
|
|
break loop
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *hub) closed() bool {
|
2024-08-27 10:04:05 -07:00
|
|
|
return !h.open.Load()
|
2020-08-26 13:27:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (h *hub) len() int {
|
2024-08-27 10:04:05 -07:00
|
|
|
return h.sessions.len()
|
2020-08-26 13:27:00 -07:00
|
|
|
}
|
2023-03-11 09:14:49 -08:00
|
|
|
|
|
|
|
func (h *hub) all() []*Session {
|
2024-08-27 10:04:05 -07:00
|
|
|
return h.sessions.all()
|
2023-03-11 09:14:49 -08:00
|
|
|
}
|