Make Handler an interface type; make dispatcher private; correctly unbox ev.

This commit is contained in:
Alex Bramley 2011-07-27 17:49:34 +01:00
parent 2c10e19f58
commit cce112465f
1 changed files with 35 additions and 22 deletions

View File

@ -8,24 +8,37 @@ import (
)
type HandlerID uint32
type Handler struct {
Run func(...interface{})
ID HandlerID
}
var hidCounter uint32 = 0
func NewHandlerID() HandlerID {
return HandlerID(atomic.AddUint32(&hidCounter, 1))
}
func NewHandler(h func(...interface{})) *Handler {
return &Handler{h, NewHandlerID()}
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 EventRegistry interface {
AddHandler(name string, h *Handler)
DelHandler(h *Handler)
AddHandler(name string, h Handler)
DelHandler(h Handler)
Dispatch(name string, ev ...interface{})
ClearEvents(name string)
}
@ -34,7 +47,7 @@ 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{})
dispatcher func(r *registry, name string, ev ...interface{})
}
func NewRegistry() *registry {
@ -43,7 +56,7 @@ func NewRegistry() *registry {
return r
}
func (r *registry) AddHandler(name string, h *Handler) {
func (r *registry) AddHandler(name string, h Handler) {
name = strings.ToLower(name)
r.Lock()
defer r.Unlock()
@ -52,20 +65,20 @@ func (r *registry) AddHandler(name string, h *Handler) {
}
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 {
if e.Value.(Handler).Id() == h.Id() {
return
}
}
r.events[name].PushBack(h)
}
func (r *registry) DelHandler(h *Handler) {
func (r *registry) DelHandler(h Handler) {
// This is a bit brute-force. Don't add too many handlers!
r.Lock()
defer r.Unlock()
for _, l := range r.events {
for e := l.Front(); e != nil; e = e.Next() {
if e.Value.(*Handler).ID == h.ID {
if e.Value.(Handler).Id() == h.Id() {
l.Remove(e)
}
}
@ -73,15 +86,15 @@ func (r *registry) DelHandler(h *Handler) {
}
func (r *registry) Dispatch(name string, ev ...interface{}) {
r.Dispatcher(r, name, ev)
r.dispatcher(r, name, ev...)
}
func (r *registry) Parallel() {
r.Dispatcher = (*registry).parallelDispatch
r.dispatcher = (*registry).parallelDispatch
}
func (r *registry) Serial() {
r.Dispatcher = (*registry).serialDispatch
r.dispatcher = (*registry).serialDispatch
}
func (r *registry) parallelDispatch(name string, ev ...interface{}) {
@ -90,8 +103,8 @@ func (r *registry) parallelDispatch(name string, ev ...interface{}) {
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)
h := e.Value.(Handler)
go h.Run(ev...)
}
}
}
@ -101,13 +114,13 @@ func (r *registry) serialDispatch(name string, ev ...interface{}) {
r.RLock()
defer r.RUnlock()
if l, ok := r.events[name]; ok {
hlist := make([]*Handler, 0, l.Len())
hlist := make([]Handler, 0, l.Len())
for e := l.Front(); e != nil; e = e.Next() {
hlist = append(hlist, e.Value.(*Handler))
hlist = append(hlist, e.Value.(Handler))
}
go func() {
for _, h := range hlist {
h.Run(ev)
h.Run(ev...)
}
}()
}