eve

Tiny event emitter for Go
git clone git://git.lair.cx/eve
Log | Files | Refs | LICENSE

commit de5eea1809ad05e71312899f669ed25141c1ed89
Author: Yongbin Kim <iam@yongbin.kim>
Date:   Fri,  3 Nov 2023 12:52:56 +0900

First commit

Diffstat:
A.gitignore | 23+++++++++++++++++++++++
ALICENSE | 15+++++++++++++++
Aeve.go | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ago.mod | 5+++++
Ago.sum | 2++
5 files changed, 110 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,23 @@ +# Allowlisting gitignore template for GO projects prevents us +# from adding various unwanted local files, such as generated +# files, developer configurations or IDE-specific files etc. +# +# Recommended: Go.AllowList.gitignore + +# Ignore everything +* + +# But not these files... +!/.gitignore + +!*.go +!go.sum +!go.mod + +!README.md +!LICENSE + +# !Makefile + +# ...even if they are in subdirectories +!*/ diff --git a/LICENSE b/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2023 Yongbin Kim + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/eve.go b/eve.go @@ -0,0 +1,65 @@ +package eve + +import ( + "context" + "sync" + + "go.uber.org/multierr" +) + +type ( + eventFn[E any] func(ctx context.Context, e E) error + eventMap[E any] map[uint64]eventFn[E] +) + +type Event[E any] interface { + On(fn eventFn[E]) func() + Emit(ctx context.Context, event E) error +} + +type event[E any] struct { + mu sync.Mutex + acc uint64 + handlers map[uint64]eventFn[E] +} + +func New[E any]() Event[E] { + return &event[E]{ + handlers: make(eventMap[E]), + } +} + +func (e *event[E]) On(fn eventFn[E]) func() { + e.mu.Lock() + + id := e.acc + e.acc++ + + e.handlers[id] = fn + + e.mu.Unlock() + + canceled := false + return func() { + if canceled { + return + } + + e.mu.Lock() + delete(e.handlers, id) + e.mu.Unlock() + } +} + +func (e *event[E]) Emit(ctx context.Context, event E) error { + e.mu.Lock() + defer e.mu.Unlock() + + var err error + + for _, fn := range e.handlers { + multierr.Append(err, fn(ctx, event)) + } + + return err +} diff --git a/go.mod b/go.mod @@ -0,0 +1,5 @@ +module go.lair.cx/eve + +go 1.21.2 + +require go.uber.org/multierr v1.11.0 // indirect diff --git a/go.sum b/go.sum @@ -0,0 +1,2 @@ +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=