// Copyright 2013-2014 Fuzamei tech Ltd. All rights reserved. package event import ( "math/rand" "sync" "time" ) func init() { rand.Seed(time.Now().UnixNano()) } type EventHandler func(v interface{}) error type Event struct { sync.RWMutex handlers map[int64]EventHandler } func (e *Event) Attach(handler EventHandler) int64 { e.Lock() defer e.Unlock() for { n := rand.Int63() _, ok := e.handlers[n] if !ok { e.handlers[n] = handler return n } } } func (e *Event) Detach(handle int64) { e.Lock() delete(e.handlers, handle) e.Unlock() } func (e *Event) DetachAll() { e.Lock() e.handlers = nil e.Unlock() } func (e *Event) publish(v interface{}) { e.Lock() for k, h := range e.handlers { // if call e.Lock() in h(v), should deadlock, // so must Unlock, and then Lock e.Unlock() if h(v) != nil { e.Detach(k) } e.Lock() } e.Unlock() } type EventPublisher struct { event Event } func (p *EventPublisher) Event() *Event { if p.event.handlers == nil { p.event.handlers = make(map[int64]EventHandler) } return &p.event } func (p *EventPublisher) Publish(v interface{}) { p.event.publish(v) }