package event
type Event struct {
Type string
data interface{}
}
func NewEvent(eventType string, data interface{}) Event {
return Event{
Type: eventType,
data: data,
}
}
func (e *Event) Data() interface{} {
return e.Data
}
type EventChan chan Event
type EventTarget struct {
listeners map[string][]func(Event)
mu sync.RWMutex
}
func NewEventTarget() *EventTarget {
return &EventTarget{
listeners: make(map[string][]func(Event)),
}
}
func (et *EventTarget) AddListener(eventType string, listener func(Event)) {
et.mu.Lock()
defer et.mu.Unlock()
if _, ok := et.listeners[eventType]; !ok {
et.listeners[eventType] = make([]func(Event), 0)
}
et.listeners[eventType] = append(et.listeners[eventType], listener)
}
func (et *EventTarget) RemoveListener(eventType string, listener func(Event)) {
et.mu.Lock()
defer et.mu.Unlock()
if listeners, ok := et.listeners[eventType]; ok {
for i, l := range listeners {
if fmt.Sprintf("%p", l) == fmt.Sprintf("%p", listener) {
et.listeners[eventType] = append(listeners[:i], listeners[i+1:]...)
break
}
}
}
}
func (et *EventTarget) Dispatch(event Event) {
et.mu.RLock()
et.mu.RUnlock()
if listeners, ok := et.listeners[event.Type]; ok {
for _, l := range listeners {
l(event)
}
}
}
func (et *EventTarget) WaitForEvent(eventType string, timeout time.Duration) (Event, error) {
eventChan := make(EventChan, 1)
listener := func(event Event) {
select {
case eventChan <- event
default:
}
}
et.AddListener(eventType, listener)
defer et.RemoveListener(eventType, listener)
select {
case targetEvent := <- eventChan:
return targetEvent, nil
case <-time.After(timeout):
return Event{}, errors.New(fmt.Sprintf("timeout %v", timeout))
}
}