Files
go-astikit/event.go
2025-02-13 11:37:23 +01:00

103 lines
1.7 KiB
Go

package astikit
import (
"sync"
)
type EventHandler func(payload any) (delete bool)
type EventName string
type EventManager struct {
handlerCount uint64
// We use a map[int]... so that deletion is as smooth as possible
hs map[EventName]map[uint64]EventHandler
m *sync.Mutex
}
func NewEventManager() *EventManager {
return &EventManager{
hs: make(map[EventName]map[uint64]EventHandler),
m: &sync.Mutex{},
}
}
func (m *EventManager) On(n EventName, h EventHandler) uint64 {
// Lock
m.m.Lock()
defer m.m.Unlock()
// Make sure event name exists
if _, ok := m.hs[n]; !ok {
m.hs[n] = make(map[uint64]EventHandler)
}
// Increment handler count
m.handlerCount++
// Add handler
m.hs[n][m.handlerCount] = h
// Return id
return m.handlerCount
}
func (m *EventManager) Off(id uint64) {
// Lock
m.m.Lock()
defer m.m.Unlock()
// Loop through handlers
for _, ids := range m.hs {
// Loop through ids
for v := range ids {
// Id matches
if id == v {
delete(ids, id)
}
}
}
}
func (m *EventManager) Emit(n EventName, payload any) {
// Loop through handlers
for _, h := range m.handlers(n) {
if h.h(payload) {
m.Off(h.id)
}
}
}
type eventManagerHandler struct {
h EventHandler
id uint64
}
func (m *EventManager) handlers(n EventName) (hs []eventManagerHandler) {
// Lock
m.m.Lock()
defer m.m.Unlock()
// Index handlers
hsm := make(map[uint64]eventManagerHandler)
var ids []uint64
if _, ok := m.hs[n]; ok {
for id, h := range m.hs[n] {
hsm[id] = eventManagerHandler{
h: h,
id: id,
}
ids = append(ids, id)
}
}
// Sort ids
SortUint64(ids)
// Append
for _, id := range ids {
hs = append(hs, hsm[id])
}
return
}