diff options
Diffstat (limited to 'eventer')
-rw-r--r-- | eventer/eventer.go | 79 | ||||
-rw-r--r-- | eventer/eventer_test.go | 66 |
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) + } +} |