aboutsummaryrefslogtreecommitdiffstats
path: root/eventer
diff options
context:
space:
mode:
Diffstat (limited to 'eventer')
-rw-r--r--eventer/eventer.go79
-rw-r--r--eventer/eventer_test.go66
2 files changed, 145 insertions, 0 deletions
diff --git a/eventer/eventer.go b/eventer/eventer.go
new file mode 100644
index 000000000..fb2f299a3
--- /dev/null
+++ b/eventer/eventer.go
@@ -0,0 +1,79 @@
+package eventer
+
+// Basic receiver interface.
+type Receiver interface {
+ Send(Event)
+}
+
+// Receiver as channel
+type Channel chan Event
+
+func (self Channel) Send(ev Event) {
+ self <- ev
+}
+
+// Receiver as function
+type Function func(ev Event)
+
+func (self Function) Send(ev Event) {
+ self(ev)
+}
+
+type Event struct {
+ Type string
+ Data interface{}
+}
+
+type Channels map[string][]Receiver
+
+type EventMachine struct {
+ channels Channels
+}
+
+func New() *EventMachine {
+ return &EventMachine{
+ channels: make(Channels),
+ }
+}
+
+func (self *EventMachine) add(typ string, r Receiver) {
+ self.channels[typ] = append(self.channels[typ], r)
+}
+
+// Generalised methods for the known receiver types
+// * Channel
+// * Function
+func (self *EventMachine) On(typ string, r interface{}) {
+ if eventFunc, ok := r.(func(Event)); ok {
+ self.RegisterFunc(typ, eventFunc)
+ } else if eventChan, ok := r.(Channel); ok {
+ self.RegisterChannel(typ, eventChan)
+ } else {
+ panic("Invalid type for EventMachine::On")
+ }
+}
+
+func (self *EventMachine) RegisterChannel(typ string, c Channel) {
+ self.add(typ, c)
+}
+
+func (self *EventMachine) RegisterFunc(typ string, f Function) {
+ self.add(typ, f)
+}
+
+func (self *EventMachine) Register(typ string) Channel {
+ c := make(Channel, 1)
+ self.add(typ, c)
+
+ return c
+}
+
+func (self *EventMachine) Post(typ string, data interface{}) {
+ if self.channels[typ] != nil {
+ ev := Event{typ, data}
+ for _, receiver := range self.channels[typ] {
+ // Blocking is OK. These are internals and need to be handled
+ receiver.Send(ev)
+ }
+ }
+}
diff --git a/eventer/eventer_test.go b/eventer/eventer_test.go
new file mode 100644
index 000000000..b35267af6
--- /dev/null
+++ b/eventer/eventer_test.go
@@ -0,0 +1,66 @@
+package eventer
+
+import "testing"
+
+func TestChannel(t *testing.T) {
+ eventer := New(nil)
+
+ c := make(Channel, 1)
+ eventer.RegisterChannel("test", c)
+ eventer.Post("test", "hello world")
+
+ res := <-c
+
+ if res.Data.(string) != "hello world" {
+ t.Error("Expected event with data 'hello world'. Got", res.Data)
+ }
+}
+
+func TestFunction(t *testing.T) {
+ eventer := New(nil)
+
+ var data string
+ eventer.RegisterFunc("test", func(ev Event) {
+ data = ev.Data.(string)
+ })
+ eventer.Post("test", "hello world")
+
+ if data != "hello world" {
+ t.Error("Expected event with data 'hello world'. Got", data)
+ }
+}
+
+func TestRegister(t *testing.T) {
+ eventer := New(nil)
+
+ c := eventer.Register("test")
+ eventer.Post("test", "hello world")
+
+ res := <-c
+
+ if res.Data.(string) != "hello world" {
+ t.Error("Expected event with data 'hello world'. Got", res.Data)
+ }
+}
+
+func TestOn(t *testing.T) {
+ eventer := New(nil)
+
+ c := make(Channel, 1)
+ eventer.On("test", c)
+
+ var data string
+ eventer.On("test", func(ev Event) {
+ data = ev.Data.(string)
+ })
+ eventer.Post("test", "hello world")
+
+ res := <-c
+ if res.Data.(string) != "hello world" {
+ t.Error("Expected channel event with data 'hello world'. Got", res.Data)
+ }
+
+ if data != "hello world" {
+ t.Error("Expected function event with data 'hello world'. Got", data)
+ }
+}