core/observer/observer.go
package observer
import (
"github.com/cheekybits/genny/generic"
"sync"
)
// Key is the type used for ginny to generate generics.
type Key generic.Type
// KeyObserver implements an event manager that allows us to add/remove listeners at will
// listeners can be added on an event "e" and pass a channel in. Every time an event "e"
// is emitted, all listeners listening on channel "e" will receive that event.
// see https://flaviocopes.com/golang-event-listeners/ for details.
//
// Deprecated: this should be replaced by ethereums's event subscription: https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.10.5/event#Subscription
type KeyObserver struct {
listeners map[Key][]chan interface{}
mux sync.RWMutex
}
// NewKeyObserver creates a new observer.
func NewKeyObserver() *KeyObserver {
return &KeyObserver{
listeners: nil,
mux: sync.RWMutex{},
}
}
// AddListener adds an event listener to the KeyObserver struct instance. This listener
// will receive all events on event "e" on channel "ch".
func (b *KeyObserver) AddListener(e Key, ch chan interface{}) {
b.mux.Lock()
defer b.mux.Unlock()
if b.listeners == nil {
b.listeners = make(map[Key][]chan interface{})
}
b.listeners[e] = append(b.listeners[e], ch)
}
// RemoveListener removes an event listener from the KeyObserver struct instance.
// Note: listeners must be removed before the channel is closed to prevent a race condition.
func (b *KeyObserver) RemoveListener(e Key, ch chan interface{}) {
b.mux.Lock()
defer b.mux.Unlock()
if _, ok := b.listeners[e]; ok {
for i := range b.listeners[e] {
if b.listeners[e][i] == ch {
b.listeners[e] = append(b.listeners[e][:i], b.listeners[e][i+1:]...)
break
}
}
}
}
// Emit emits an event on the KeyObserver struct instance. The event is received by all listeners
// listening on event.
func (b *KeyObserver) Emit(e Key, response interface{}) {
b.mux.RLock()
defer b.mux.RUnlock()
if _, ok := b.listeners[e]; ok {
for _, handler := range b.listeners[e] {
go func(handler chan interface{}) {
handler <- response
}(handler)
}
}
}