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 package client
import ( import (
"github.com/fluffle/goirc/logging"
"runtime" "runtime"
"strings" "strings"
"sync" "sync"
"github.com/fluffle/goirc/logging"
) )
// Handlers are triggered on incoming Lines from the server, with the handler // 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() hs.RLock()
defer hs.RUnlock() defer hs.RUnlock()
ev := strings.ToLower(line.Cmd)
list, ok := hs.set[ev] list, ok := hs.set[ev]
if !ok { 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 { 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) wg.Add(1)
go func(hn *hNode) { go func(hn *hNode) {
hn.Handle(conn, line.Copy()) hn.Handle(conn, line.Copy())