Avoid holding hSet lock while executing handlers. Fixes #102.

This commit is contained in:
Alex Bramley 2017-07-25 20:28:24 +01:00
parent 2ece5aab67
commit c981f8f568
1 changed files with 15 additions and 5 deletions

View File

@ -1,10 +1,11 @@
package client
import (
"github.com/fluffle/goirc/logging"
"runtime"
"strings"
"sync"
"github.com/fluffle/goirc/logging"
)
// Handlers are triggered on incoming Lines from the server, with the handler
@ -128,16 +129,25 @@ func (hs *hSet) remove(hn *hNode) {
}
}
func (hs *hSet) dispatch(conn *Conn, line *Line) {
func (hs *hSet) getHandlers(ev string) []*hNode {
hs.RLock()
defer hs.RUnlock()
ev := strings.ToLower(line.Cmd)
list, ok := hs.set[ev]
if !ok {
return
return nil
}
wg := &sync.WaitGroup{}
// Copy current list of handlers to a temporary slice under the lock.
handlers := make([]*hNode, 0)
for hn := list.start; hn != nil; hn = hn.next {
handlers = append(handlers, hn)
}
return handlers
}
func (hs *hSet) dispatch(conn *Conn, line *Line) {
ev := strings.ToLower(line.Cmd)
wg := &sync.WaitGroup{}
for _, hn := range hs.getHandlers(ev) {
wg.Add(1)
go func(hn *hNode) {
hn.Handle(conn, line.Copy())