Browse Source

Small performance improvement. Added tests.

Chris Rhodes 9 years ago
parent
commit
88335b6f54
3 changed files with 50 additions and 6 deletions
  1. 7 5
      discord.go
  2. 36 0
      discord_test.go
  3. 7 1
      structs.go

+ 7 - 5
discord.go

@@ -151,10 +151,10 @@ func (s *Session) AddHandler(handler interface{}) {
 
 	handlers := s.Handlers[eventType]
 	if handlers == nil {
-		handlers = []interface{}{}
+		handlers = []reflect.Value{}
 	}
 
-	handlers = append(handlers, handler)
+	handlers = append(handlers, reflect.ValueOf(handler))
 	s.Handlers[eventType] = handlers
 }
 
@@ -162,15 +162,17 @@ func (s *Session) handle(event interface{}) {
 	s.RLock()
 	defer s.RUnlock()
 
+	handlerParameters := []reflect.Value{reflect.ValueOf(s), reflect.ValueOf(event)}
+
 	if handlers, ok := s.Handlers[reflect.TypeOf(event)]; ok {
 		for _, handler := range handlers {
-			reflect.ValueOf(handler).Call([]reflect.Value{reflect.ValueOf(s), reflect.ValueOf(event)})
+			handler.Call(handlerParameters)
 		}
 	}
 
 	if handlers, ok := s.Handlers[nil]; ok {
 		for _, handler := range handlers {
-			reflect.ValueOf(handler).Call([]reflect.Value{reflect.ValueOf(s), reflect.ValueOf(event)})
+			handler.Call(handlerParameters)
 		}
 	}
 }
@@ -178,7 +180,7 @@ func (s *Session) handle(event interface{}) {
 // initialize adds all internal handlers and state tracking handlers.
 func (s *Session) initialize() {
 	s.Lock()
-	s.Handlers = map[interface{}][]interface{}{}
+	s.Handlers = map[interface{}][]reflect.Value{}
 	s.Unlock()
 
 	s.AddHandler(s.onEvent)

+ 36 - 0
discord_test.go

@@ -224,3 +224,39 @@ func TestOpenClose(t *testing.T) {
 		t.Fatalf("TestClose, d.Close failed: %+v", err)
 	}
 }
+
+func TestHandlers(t *testing.T) {
+	testHandlerCalled := false
+	testHandler := func(s *Session, t *testing.T) {
+		testHandlerCalled = true
+	}
+
+	interfaceHandlerCalled := false
+	interfaceHandler := func(s *Session, i interface{}) {
+		interfaceHandlerCalled = true
+	}
+
+	bogusHandlerCalled := false
+	bogusHandler := func(s *Session, se *Session) {
+		bogusHandlerCalled = true
+	}
+
+	d := Session{}
+	d.AddHandler(testHandler)
+	d.AddHandler(interfaceHandler)
+	d.AddHandler(bogusHandler)
+
+	d.handle(t)
+
+	if !testHandlerCalled {
+		t.Fatalf("testHandler was not called.")
+	}
+
+	if !interfaceHandlerCalled {
+		t.Fatalf("interfaceHandler was not called.")
+	}
+
+	if bogusHandlerCalled {
+		t.Fatalf("bogusHandler was called.")
+	}
+}

+ 7 - 1
structs.go

@@ -13,6 +13,7 @@ package discordgo
 
 import (
 	"encoding/json"
+	"reflect"
 	"sync"
 	"time"
 
@@ -29,7 +30,12 @@ type Session struct {
 	Token string // Authentication token for this session
 	Debug bool   // Debug for printing JSON request/responses
 
-	Handlers map[interface{}][]interface{}
+	// This is a mapping of event structs to a reflected value
+	// for event handlers.
+	// We store the reflected value instead of the function
+	// reference as it is more performant, instead of re-reflecting
+	// the function each event.
+	Handlers map[interface{}][]reflect.Value
 
 	// Exposed but should not be modified by User.
 	SessionID  string // from websocket READY packet