diff --git a/client/connection.go b/client/connection.go index aaf3f14..e4d474e 100644 --- a/client/connection.go +++ b/client/connection.go @@ -3,7 +3,7 @@ package client import ( "bufio" "crypto/tls" - "github.com/fluffle/goirc/event" + "github.com/fluffle/goevent/event" "github.com/fluffle/golog/logging" "github.com/fluffle/goirc/state" "fmt" diff --git a/client/connection_test.go b/client/connection_test.go index 8f22e41..b7b4888 100644 --- a/client/connection_test.go +++ b/client/connection_test.go @@ -2,7 +2,7 @@ package client import ( "bufio" - "github.com/fluffle/goirc/event" + "github.com/fluffle/goevent/event" "github.com/fluffle/golog/logging" "github.com/fluffle/goirc/state" "gomock.googlecode.com/hg/gomock" diff --git a/client/handlers.go b/client/handlers.go index 078f228..2624a71 100644 --- a/client/handlers.go +++ b/client/handlers.go @@ -4,7 +4,7 @@ package client // to manage tracking an irc connection etc. import ( - "github.com/fluffle/goirc/event" + "github.com/fluffle/goevent/event" "strings" ) diff --git a/client/state_handlers.go b/client/state_handlers.go index 3da84dc..efd8c48 100644 --- a/client/state_handlers.go +++ b/client/state_handlers.go @@ -4,7 +4,7 @@ package client // to manage tracking state for an IRC connection import ( - "github.com/fluffle/goirc/event" + "github.com/fluffle/goevent/event" "strings" ) diff --git a/event/mock_registry.go b/event/mock_registry.go deleted file mode 100644 index bcdbc1b..0000000 --- a/event/mock_registry.go +++ /dev/null @@ -1,127 +0,0 @@ -// Automatically generated by MockGen. DO NOT EDIT! -// Source: registry.go - -package event - -import ( - gomock "gomock.googlecode.com/hg/gomock" -) - -// Mock of Handler interface -type MockHandler struct { - ctrl *gomock.Controller - recorder *_MockHandlerRecorder -} - -// Recorder for MockHandler (not exported) -type _MockHandlerRecorder struct { - mock *MockHandler -} - -func NewMockHandler(ctrl *gomock.Controller) *MockHandler { - mock := &MockHandler{ctrl: ctrl} - mock.recorder = &_MockHandlerRecorder{mock} - return mock -} - -func (m *MockHandler) EXPECT() *_MockHandlerRecorder { - return m.recorder -} - -func (m *MockHandler) Run(_param0 ...interface{}) { - m.ctrl.Call(m, "Run", _param0) -} - -func (mr *_MockHandlerRecorder) Run(arg0 ...interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "Run", arg0) -} - -func (m *MockHandler) Id() HandlerID { - ret := m.ctrl.Call(m, "Id") - ret0, _ := ret[0].(HandlerID) - return ret0 -} - -func (mr *_MockHandlerRecorder) Id() *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "Id") -} -// Mock of EventDispatcher interface -type MockEventDispatcher struct { - ctrl *gomock.Controller - recorder *_MockEventDispatcherRecorder -} - -// Recorder for MockEventDispatcher (not exported) -type _MockEventDispatcherRecorder struct { - mock *MockEventDispatcher -} - -func NewMockEventDispatcher(ctrl *gomock.Controller) *MockEventDispatcher { - mock := &MockEventDispatcher{ctrl: ctrl} - mock.recorder = &_MockEventDispatcherRecorder{mock} - return mock -} - -func (m *MockEventDispatcher) EXPECT() *_MockEventDispatcherRecorder { - return m.recorder -} - -func (m *MockEventDispatcher) Dispatch(name string, ev ...interface{}) { - m.ctrl.Call(m, "Dispatch", name, ev) -} - -func (mr *_MockEventDispatcherRecorder) Dispatch(arg0 interface{}, arg1 ...interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "Dispatch", arg0, arg1) -} -// Mock of EventRegistry interface -type MockEventRegistry struct { - ctrl *gomock.Controller - recorder *_MockEventRegistryRecorder -} - -// Recorder for MockEventRegistry (not exported) -type _MockEventRegistryRecorder struct { - mock *MockEventRegistry -} - -func NewMockEventRegistry(ctrl *gomock.Controller) *MockEventRegistry { - mock := &MockEventRegistry{ctrl: ctrl} - mock.recorder = &_MockEventRegistryRecorder{mock} - return mock -} - -func (m *MockEventRegistry) EXPECT() *_MockEventRegistryRecorder { - return m.recorder -} - -func (m *MockEventRegistry) AddHandler(h Handler, names ...string) { - m.ctrl.Call(m, "AddHandler", h, names) -} - -func (mr *_MockEventRegistryRecorder) AddHandler(arg0 interface{}, arg1 ...string) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "AddHandler", arg0, arg1) -} - -func (m *MockEventRegistry) DelHandler(h Handler, names ...string) { - m.ctrl.Call(m, "DelHandler", h, names) -} - -func (mr *_MockEventRegistryRecorder) DelHandler(arg0 interface{}, arg1 ...string) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "DelHandler", arg0, arg1) -} - -func (m *MockEventRegistry) Dispatch(name string, ev ...interface{}) { - m.ctrl.Call(m, "Dispatch", name, ev) -} - -func (mr *_MockEventRegistryRecorder) Dispatch(arg0 interface{}, arg1 ...interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "Dispatch", arg0, arg1) -} - -func (m *MockEventRegistry) ClearEvents(name string) { - m.ctrl.Call(m, "ClearEvents", name) -} - -func (mr *_MockEventRegistryRecorder) ClearEvents(arg0 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCall(mr.mock, "ClearEvents", arg0) -} diff --git a/event/registry.go b/event/registry.go deleted file mode 100644 index 7df894d..0000000 --- a/event/registry.go +++ /dev/null @@ -1,162 +0,0 @@ -package event - -import ( - "container/list" - "strings" - "sync/atomic" - "sync" -) - -type HandlerID uint32 - -var hidCounter uint32 = 0 - -func NewHandlerID() HandlerID { - return HandlerID(atomic.AddUint32(&hidCounter, 1)) -} - -type Handler interface { - Run(...interface{}) - Id() HandlerID -} - -type basicHandler struct { - fn func(...interface{}) - id HandlerID -} - -func (h *basicHandler) Run(ev ...interface{}) { - h.fn(ev...) -} - -func (h *basicHandler) Id() HandlerID { - return h.id -} - -func NewHandler(h func(...interface{})) Handler { - return &basicHandler{h, NewHandlerID()} -} - -type EventDispatcher interface { - Dispatch(name string, ev ...interface{}) -} - -type EventRegistry interface { - AddHandler(h Handler, names ...string) - DelHandler(h Handler, names ...string) - Dispatch(name string, ev ...interface{}) - ClearEvents(name string) -} - -type registry struct { - // Event registry as a lockable map of linked-lists - sync.RWMutex - events map[string]*list.List - dispatcher func(r *registry, name string, ev ...interface{}) -} - -func NewRegistry() *registry { - r := ®istry{events: make(map[string]*list.List)} - r.Parallel() - return r -} - -func (r *registry) AddHandler(h Handler, names ...string) { - if len(names) == 0 { - return - } - r.Lock() - defer r.Unlock() -N: for _, name := range names { - name = strings.ToLower(name) - if _, ok := r.events[name]; !ok { - r.events[name] = list.New() - } - for e := r.events[name].Front(); e != nil; e = e.Next() { - // Check we're not adding a duplicate handler to this event - if e.Value.(Handler).Id() == h.Id() { - continue N - } - } - r.events[name].PushBack(h) - } -} - -func _del(l *list.List, id HandlerID) bool { - for e := l.Front(); e != nil; e = e.Next() { - if e.Value.(Handler).Id() == id { - l.Remove(e) - } - } - return l.Len() == 0 -} - -func (r *registry) DelHandler(h Handler, names ...string) { - r.Lock() - defer r.Unlock() - if len(names) == 0 { - for name, l := range r.events { - if _del(l, h.Id()) { - r.events[name] = nil, false - } - } - } else { - for _, name := range names { - name = strings.ToLower(name) - if l, ok := r.events[name]; ok { - if _del(l, h.Id()) { - r.events[name] = nil, false - } - } - } - } -} - -func (r *registry) Dispatch(name string, ev ...interface{}) { - r.dispatcher(r, strings.ToLower(name), ev...) -} - -func (r *registry) ClearEvents(name string) { - name = strings.ToLower(name) - r.Lock() - defer r.Unlock() - if l, ok := r.events[name]; ok { - l.Init() // I hope this is enough to GC all list elements. - r.events[name] = nil, false - } -} - -func (r *registry) Parallel() { - r.dispatcher = (*registry).parallelDispatch -} - -func (r *registry) Serial() { - r.dispatcher = (*registry).serialDispatch -} - -func (r *registry) parallelDispatch(name string, ev ...interface{}) { - r.RLock() - defer r.RUnlock() - if l, ok := r.events[name]; ok { - for e := l.Front(); e != nil; e = e.Next() { - h := e.Value.(Handler) - go h.Run(ev...) - } - } -} - -func (r *registry) serialDispatch(name string, ev ...interface{}) { - r.RLock() - defer r.RUnlock() - if l, ok := r.events[name]; ok { - hlist := make([]Handler, l.Len()) - for e, i := l.Front(), 0; e != nil; e, i = e.Next(), i+1 { - hlist[i] = e.Value.(Handler) - } - go func() { - for _, h := range hlist { - h.Run(ev...) - } - }() - } -} diff --git a/event/registry_test.go b/event/registry_test.go deleted file mode 100644 index 6b775d2..0000000 --- a/event/registry_test.go +++ /dev/null @@ -1,224 +0,0 @@ -package event - -// oh hey unit tests. or functionality tests, or something. - -import ( - "testing" - "time" -) - -func TestAddDelHandler(t *testing.T) { - r := NewRegistry() - - if len(r.events) != 0 { - t.Errorf("New registry has non-zero-length event map.") - } - - h1 := NewHandler(func(ev ...interface{}) {}) - h2 := NewHandler(func(ev ...interface{}) {}) - - // Ensure that a handler with no events to handle doesn't get added - r.AddHandler(h1) - if len(r.events) != 0 { - t.Errorf("Adding handler with no events succeded.") - } - - // Add h1 to a couple of events. - r.AddHandler(h1, "e1", "E2") - if len(r.events) != 2 { - t.Errorf("Adding handler h1 to events failed.") - } - if l, ok := r.events["e1"]; !ok || l.Len() != 1 || - l.Front().Value != h1 { - t.Errorf("Handler h1 not added to event e1 correctly.") - } - if l, ok := r.events["e2"]; !ok || l.Len() != 1 || - l.Front().Value != h1 { - t.Errorf("Handler h1 not added to event e2 correctly.") - } - - // Add h2 to a couple of events. - r.AddHandler(h2, "e2", "E3") - if len(r.events) != 3 { - t.Errorf("Adding handler h2 to events failed.") - } - if l, ok := r.events["e2"]; !ok || l.Len() != 2 || - l.Front().Next().Value.(Handler) != h2 { - t.Errorf("Handler h2 not added to event e2 correctly.") - } - if l, ok := r.events["e3"]; !ok || l.Len() != 1 || - l.Front().Value.(Handler) != h2 { - t.Errorf("Handler h2 not added to event e3 correctly.") - } - - // Add h1 to some more events, which it may be in already. - r.AddHandler(h1, "e2", "e3", "e4", "e5") - if len(r.events) != 5 { - t.Errorf("Adding handler h1 to more events failed.") - println(len(r.events)) - } - if l, ok := r.events["e2"]; !ok || l.Len() != 2 { - t.Errorf("Handler h1 added twice to event e2.") - } - if l, ok := r.events["e3"]; !ok || l.Len() != 2 || - l.Front().Next().Value.(Handler) != h1 { - t.Errorf("Handler h1 not added to event e3 correctly.") - } - - // Add h2 to a few more events, for testing delete - r.AddHandler(h2, "e5", "e6") - if len(r.events) != 6 { - t.Errorf("Adding handler h2 to more events failed.") - } - - // Currently, we have the following handlers set up: - // h1: e1 e2 e3 e4 e5 - // h2: e2 e3 e5 e6 - // NOTE: for e3, h2 is first and h1 is second in the linked list - - // Delete h1 from a few events. This should remove e4 completely. - r.DelHandler(h1, "e2", "E3", "e4") - if _, ok := r.events["e4"]; ok || len(r.events) != 5 { - t.Errorf("Deleting h1 from some events failed to remove e4.") - } - if l, ok := r.events["e2"]; !ok || l.Len() != 1 || - l.Front().Value.(Handler) != h2 { - t.Errorf("Handler h1 not deleted from event e2 correctly.") - } - if l, ok := r.events["e3"]; !ok || l.Len() != 1 || - l.Front().Value.(Handler) != h2 { - t.Errorf("Handler h1 not deleted from event e3 correctly.") - } - - // Now, we have the following handlers set up: - // h1: e1 e5 - // h2: e2 e3 e5 e6 - - // Delete h2 from a couple of events, removing e2 and e3. - // Deleting h2 from a handler it is not in should not cause problems. - r.DelHandler(h2, "e1", "e2", "e3") - if len(r.events) != 3 { - t.Errorf("Deleting h2 from some events failed to remove e{2,3}.") - } - if l, ok := r.events["e1"]; !ok || l.Len() != 1 || - l.Front().Value.(Handler) != h1 { - t.Errorf("Handler h1 deleted from event e1 incorrectly.") - } - - // Delete h1 completely. - r.DelHandler(h1) - if _, ok := r.events["e1"]; ok || len(r.events) != 2 { - t.Errorf("Deleting h1 completely failed to remove e1.") - } - if l, ok := r.events["e5"]; !ok || l.Len() != 1 || - l.Front().Value.(Handler) != h2 { - t.Errorf("Handler h1 deleted from event e5 incorrectly.") - } - - // Clear e5 completely - r.ClearEvents("e5") - if _, ok := r.events["e5"]; ok || len(r.events) != 1 { - t.Errorf("Deleting e5 completely failed to remove it.") - } - - // All that should be left is e6, with h2 as it's only handler. - if l, ok := r.events["e6"]; !ok || l.Len() != 1 || - l.Front().Value.(Handler) != h2 { - t.Errorf("Remaining event and handler doesn't match expectations.") - } -} - -func TestSimpleDispatch(t *testing.T) { - r := NewRegistry() - out := make(chan bool) - - h := NewHandler(func(ev ...interface{}) { - out <- ev[0].(bool) - }) - r.AddHandler(h, "send") - - r.Dispatch("send", true) - if val := <-out; !val { - t.Fail() - } - - r.Dispatch("send", false) - if val := <-out; val { - t.Fail() - } -} - -func TestParallelDispatch(t *testing.T) { - r := NewRegistry() - // ensure we have enough of a buffer that all sends complete - out := make(chan int, 5) - // handler factory :-) - factory := func(t int) Handler { - return NewHandler(func(ev ...interface{}) { - // t * 10ms sleep - time.Sleep(int64(t * 1e7)) - out <- t - }) - } - - // create some handlers and send an event to them - for _, t := range []int{5, 11, 2, 15, 8} { - r.AddHandler(factory(t), "send") - } - r.Dispatch("send") - - // If parallel dispatch is working, results from out should be in numerical order - if val := <-out; val != 2 { - t.Fail() - } - if val := <-out; val != 5 { - t.Fail() - } - if val := <-out; val != 8 { - t.Fail() - } - if val := <-out; val != 11 { - t.Fail() - } - if val := <-out; val != 15 { - t.Fail() - } -} - -func TestSerialDispatch(t *testing.T) { - r := NewRegistry() - r.Serial() - // ensure we have enough of a buffer that all sends complete - out := make(chan int, 5) - // handler factory :-) - factory := func(t int) Handler { - return NewHandler(func(ev ...interface{}) { - // t * 10ms sleep - time.Sleep(int64(t * 1e7)) - out <- t - }) - } - - // create some handlers and send an event to them - for _, t := range []int{5, 11, 2, 15, 8} { - r.AddHandler(factory(t), "send") - } - r.Dispatch("send") - - // If serial dispatch is working, results from out should be in handler order - if val := <-out; val != 5 { - t.Fail() - } - if val := <-out; val != 11 { - t.Fail() - } - if val := <-out; val != 2 { - t.Fail() - } - if val := <-out; val != 15 { - t.Fail() - } - if val := <-out; val != 8 { - t.Fail() - } -}