BREAKING CHANGES: Run callbacks in main thread and int callback id.

Execute callbacks in main thread. This will break callbacks that
use a long time to execute. Create your own thread in AddCallback
using gorutines on long running callbacks.

Use deterministic IDs for AddCallback. Changes the id from SHA-hash
to int.
This commit is contained in:
Thomas Jager
2016-02-06 21:33:04 +01:00
parent ab737c68eb
commit da78ed515c
4 changed files with 64 additions and 52 deletions

View File

@@ -1,10 +1,6 @@
package irc
import (
"crypto/sha1"
"fmt"
"math/rand"
"reflect"
"strconv"
"strings"
"time"
@@ -14,23 +10,22 @@ import (
// which takes only an Event pointer as parameter. Valid event codes are all
// IRC/CTCP commands and error/response codes. This function returns the ID of
// the registered callback for later management.
func (irc *Connection) AddCallback(eventcode string, callback func(*Event)) string {
func (irc *Connection) AddCallback(eventcode string, callback func(*Event)) int {
eventcode = strings.ToUpper(eventcode)
id := 0
if _, ok := irc.events[eventcode]; !ok {
irc.events[eventcode] = make(map[string]func(*Event))
irc.events[eventcode] = make(map[int]func(*Event))
id = 0
} else {
id = len(irc.events[eventcode])
}
h := sha1.New()
rawId := []byte(fmt.Sprintf("%v%d", reflect.ValueOf(callback).Pointer(), rand.Int63()))
h.Write(rawId)
id := fmt.Sprintf("%x", h.Sum(nil))
irc.events[eventcode][id] = callback
return id
}
// Remove callback i (ID) from the given event code. This functions returns
// true upon success, false if any error occurs.
func (irc *Connection) RemoveCallback(eventcode string, i string) bool {
func (irc *Connection) RemoveCallback(eventcode string, i int) bool {
eventcode = strings.ToUpper(eventcode)
if event, ok := irc.events[eventcode]; ok {
@@ -52,7 +47,7 @@ func (irc *Connection) ClearCallback(eventcode string) bool {
eventcode = strings.ToUpper(eventcode)
if _, ok := irc.events[eventcode]; ok {
irc.events[eventcode] = make(map[string]func(*Event))
irc.events[eventcode] = make(map[int]func(*Event))
return true
}
@@ -61,7 +56,7 @@ func (irc *Connection) ClearCallback(eventcode string) bool {
}
// Replace callback i (ID) associated with a given event code with a new callback function.
func (irc *Connection) ReplaceCallback(eventcode string, i string, callback func(*Event)) {
func (irc *Connection) ReplaceCallback(eventcode string, i int, callback func(*Event)) {
eventcode = strings.ToUpper(eventcode)
if event, ok := irc.events[eventcode]; ok {
@@ -120,7 +115,7 @@ func (irc *Connection) RunCallbacks(event *Event) {
}
for _, callback := range callbacks {
go callback(event)
callback(event)
}
} else if irc.VerboseCallbackHandler {
irc.Log.Printf("%v (0) >> %#v\n", event.Code, event)
@@ -128,21 +123,22 @@ func (irc *Connection) RunCallbacks(event *Event) {
if callbacks, ok := irc.events["*"]; ok {
if irc.VerboseCallbackHandler {
irc.Log.Printf("Wildcard %v (%v) >> %#v\n", event.Code, len(callbacks), event)
irc.Log.Printf("%v (0) >> %#v\n", event.Code, event)
}
for _, callback := range callbacks {
go callback(event)
callback(event)
}
}
}
// Set up some initial callbacks to handle the IRC/CTCP protocol.
func (irc *Connection) setupCallbacks() {
irc.events = make(map[string]map[string]func(*Event))
irc.events = make(map[string]map[int]func(*Event))
//Handle error events
irc.AddCallback("ERROR", func(e *Event) { irc.Disconnect() })
//Handle error events. This has to be called in a new thred to allow
//readLoop to exit
irc.AddCallback("ERROR", func(e *Event) { go irc.Disconnect() })
//Handle ping events
irc.AddCallback("PING", func(e *Event) { irc.SendRaw("PONG :" + e.Message()) })
@@ -223,7 +219,3 @@ func (irc *Connection) setupCallbacks() {
irc.nickcurrent = e.Arguments[0]
})
}
func init() {
rand.Seed(time.Now().UnixNano())
}