mirror of https://github.com/fluffle/goirc
Split handlers up into three groups.
This commit is contained in:
parent
12eb9c89eb
commit
144001d109
|
@ -22,7 +22,9 @@ type Conn struct {
|
||||||
cfg *Config
|
cfg *Config
|
||||||
|
|
||||||
// Handlers
|
// Handlers
|
||||||
handlers *hSet
|
intHandlers *hSet
|
||||||
|
fgHandlers *hSet
|
||||||
|
bgHandlers *hSet
|
||||||
|
|
||||||
// State tracker for nicks and channels
|
// State tracker for nicks and channels
|
||||||
st state.Tracker
|
st state.Tracker
|
||||||
|
@ -119,7 +121,9 @@ func Client(cfg *Config) *Conn {
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
in: make(chan *Line, 32),
|
in: make(chan *Line, 32),
|
||||||
out: make(chan string, 32),
|
out: make(chan string, 32),
|
||||||
handlers: handlerSet(),
|
intHandlers: handlerSet(),
|
||||||
|
fgHandlers: handlerSet(),
|
||||||
|
bgHandlers: handlerSet(),
|
||||||
stRemovers: make([]Remover, 0, len(stHandlers)),
|
stRemovers: make([]Remover, 0, len(stHandlers)),
|
||||||
lastsent: time.Now(),
|
lastsent: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ func TestClientAndStateTracking(t *testing.T) {
|
||||||
}
|
}
|
||||||
// Check that the internal handlers are correctly set up
|
// Check that the internal handlers are correctly set up
|
||||||
for k, _ := range intHandlers {
|
for k, _ := range intHandlers {
|
||||||
if _, ok := c.handlers.set[strings.ToLower(k)]; !ok {
|
if _, ok := c.intHandlers.set[strings.ToLower(k)]; !ok {
|
||||||
t.Errorf("Missing internal handler for '%s'.", k)
|
t.Errorf("Missing internal handler for '%s'.", k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ func TestClientAndStateTracking(t *testing.T) {
|
||||||
// Now enable the state tracking code and check its handlers
|
// Now enable the state tracking code and check its handlers
|
||||||
c.EnableStateTracking()
|
c.EnableStateTracking()
|
||||||
for k, _ := range stHandlers {
|
for k, _ := range stHandlers {
|
||||||
if _, ok := c.handlers.set[strings.ToLower(k)]; !ok {
|
if _, ok := c.intHandlers.set[strings.ToLower(k)]; !ok {
|
||||||
t.Errorf("Missing state handler for '%s'.", k)
|
t.Errorf("Missing state handler for '%s'.", k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ func TestClientAndStateTracking(t *testing.T) {
|
||||||
|
|
||||||
// Finally, check state tracking handlers were all removed correctly
|
// Finally, check state tracking handlers were all removed correctly
|
||||||
for k, _ := range stHandlers {
|
for k, _ := range stHandlers {
|
||||||
if _, ok := c.handlers.set[strings.ToLower(k)]; ok && k != "NICK" {
|
if _, ok := c.intHandlers.set[strings.ToLower(k)]; ok && k != "NICK" {
|
||||||
// A bit leaky, because intHandlers adds a NICK handler.
|
// A bit leaky, because intHandlers adds a NICK handler.
|
||||||
t.Errorf("State handler for '%s' not removed correctly.", k)
|
t.Errorf("State handler for '%s' not removed correctly.", k)
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,9 +121,15 @@ func (hs *hSet) dispatch(conn *Conn, line *Line) {
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
wg := &sync.WaitGroup{}
|
||||||
for hn := list.start; hn != nil; hn = hn.next {
|
for hn := list.start; hn != nil; hn = hn.next {
|
||||||
go hn.Handle(conn, line.Copy())
|
wg.Add(1)
|
||||||
|
go func(hn *hNode) {
|
||||||
|
hn.Handle(conn, line.Copy())
|
||||||
|
wg.Done()
|
||||||
|
}(hn)
|
||||||
}
|
}
|
||||||
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handlers are triggered on incoming Lines from the server, with the handler
|
// Handlers are triggered on incoming Lines from the server, with the handler
|
||||||
|
@ -133,7 +139,15 @@ func (hs *hSet) dispatch(conn *Conn, line *Line) {
|
||||||
// strings of digits like "332" (mainly because I really didn't feel like
|
// strings of digits like "332" (mainly because I really didn't feel like
|
||||||
// putting massive constant tables in).
|
// putting massive constant tables in).
|
||||||
func (conn *Conn) Handle(name string, h Handler) Remover {
|
func (conn *Conn) Handle(name string, h Handler) Remover {
|
||||||
return conn.handlers.add(name, h)
|
return conn.fgHandlers.add(name, h)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conn *Conn) HandleBG(name string, h Handler) Remover {
|
||||||
|
return conn.bgHandlers.add(name, h)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conn *Conn) handle(name string, h Handler) Remover {
|
||||||
|
return conn.intHandlers.add(name, h)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conn *Conn) HandleFunc(name string, hf HandlerFunc) Remover {
|
func (conn *Conn) HandleFunc(name string, hf HandlerFunc) Remover {
|
||||||
|
@ -141,7 +155,18 @@ func (conn *Conn) HandleFunc(name string, hf HandlerFunc) Remover {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conn *Conn) dispatch(line *Line) {
|
func (conn *Conn) dispatch(line *Line) {
|
||||||
conn.handlers.dispatch(conn, line)
|
// We run the internal handlers first, including all state tracking ones.
|
||||||
|
// This ensures that user-supplied handlers that use the tracker have a
|
||||||
|
// consistent view of the connection state in handlers that mutate it.
|
||||||
|
conn.intHandlers.dispatch(conn, line)
|
||||||
|
// Background handlers are run in parallel and do not block the event loop.
|
||||||
|
// This is useful for things that may need to do significant work.
|
||||||
|
go conn.bgHandlers.dispatch(conn, line)
|
||||||
|
// Foreground handlers have a guarantee of protocol consistency: all the
|
||||||
|
// handlers for one event will have finished before the handlers for the
|
||||||
|
// next start processing. They are run in parallel but block the event
|
||||||
|
// loop, so care should be taken to ensure these handlers are quick :-)
|
||||||
|
conn.fgHandlers.dispatch(conn, line)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conn *Conn) LogPanic(line *Line) {
|
func (conn *Conn) LogPanic(line *Line) {
|
||||||
|
|
|
@ -21,7 +21,7 @@ func (conn *Conn) addIntHandlers() {
|
||||||
for n, h := range intHandlers {
|
for n, h := range intHandlers {
|
||||||
// internal handlers are essential for the IRC client
|
// internal handlers are essential for the IRC client
|
||||||
// to function, so we don't save their Removers here
|
// to function, so we don't save their Removers here
|
||||||
conn.Handle(n, h)
|
conn.handle(n, h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ var stHandlers = map[string]HandlerFunc{
|
||||||
|
|
||||||
func (conn *Conn) addSTHandlers() {
|
func (conn *Conn) addSTHandlers() {
|
||||||
for n, h := range stHandlers {
|
for n, h := range stHandlers {
|
||||||
conn.stRemovers = append(conn.stRemovers, conn.Handle(n, h))
|
conn.stRemovers = append(conn.stRemovers, conn.handle(n, h))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue