86 lines
2.0 KiB
Go
86 lines
2.0 KiB
Go
// Package event provides a system for broadcasting events to multiple event
|
|
// handlers.
|
|
package event
|
|
|
|
// A cookie is returned when you add an event handler so you can remove it
|
|
// later if you so choose.
|
|
type Cookie interface {
|
|
// Close removes the event handler this cookie is for.
|
|
Close ()
|
|
}
|
|
|
|
// Broadcaster manages event listeners.
|
|
type Broadcaster[L any] struct {
|
|
lastID int
|
|
listeners map[int] L
|
|
}
|
|
|
|
// Connect adds a new listener to the broadcaster and returns a corresponding
|
|
// cookie.
|
|
func (broadcaster *Broadcaster[L]) Connect (listener L) Cookie {
|
|
broadcaster.ensure()
|
|
|
|
cookie := broadcaster.newCookie()
|
|
broadcaster.listeners[cookie.id] = listener
|
|
return cookie
|
|
}
|
|
|
|
// Listeners returns a map of all connected listeners.
|
|
func (broadcaster *Broadcaster[L]) Listeners () map[int] L {
|
|
broadcaster.ensure()
|
|
return broadcaster.listeners
|
|
}
|
|
|
|
func (broadcaster *Broadcaster[L]) newCookie () cookie[L] {
|
|
broadcaster.lastID ++
|
|
return cookie[L] {
|
|
id: broadcaster.lastID,
|
|
broadcaster: broadcaster,
|
|
}
|
|
}
|
|
|
|
func (broadcaster *Broadcaster[L]) ensure () {
|
|
if broadcaster.listeners == nil {
|
|
broadcaster.listeners = make(map[int] L)
|
|
}
|
|
}
|
|
|
|
// NoCookie is a cookie that does nothing when closed.
|
|
type NoCookie struct { }
|
|
func (NoCookie) Close () { }
|
|
|
|
type cookie[L any] struct {
|
|
id int
|
|
broadcaster *Broadcaster[L]
|
|
}
|
|
|
|
func (cookie cookie[L]) Close () {
|
|
delete(cookie.broadcaster.listeners, cookie.id)
|
|
}
|
|
|
|
// FuncBroadcaster is a broadcaster that manages functions with no arguments.
|
|
type FuncBroadcaster struct {
|
|
Broadcaster[func ()]
|
|
}
|
|
|
|
// Broadcast calls all connected listener funcs.
|
|
func (broadcaster *FuncBroadcaster) Broadcast () {
|
|
for _, listener := range broadcaster.Listeners() {
|
|
listener()
|
|
}
|
|
}
|
|
|
|
type multiCookie []Cookie
|
|
|
|
// MultiCookie creates a single cookie that, when closed, closes a list of other
|
|
// cookies.
|
|
func MultiCookie (cookies ...Cookie) Cookie {
|
|
return multiCookie(cookies)
|
|
}
|
|
|
|
func (cookies multiCookie) Close () {
|
|
for _, cookie := range cookies {
|
|
cookie.Close()
|
|
}
|
|
}
|