diff --git a/main.go b/main.go index 86ca5f5..ec9ec2c 100644 --- a/main.go +++ b/main.go @@ -1,23 +1,46 @@ -// Package goemitter +// Package goemitter implements an event emitter pattern similar to Node.js EventEmitter. +// It provides a way to register event listeners and emit events with data. +// +// Basic usage example: +// +// emitter := goemitter.NewEmitter() +// +// // Register an event listener +// handle := emitter.On("userConnected", func(args ...interface{}) { +// user := args[0].(string) +// fmt.Printf("User connected: %s\n", user) +// }) +// +// // Emit an event +// emitter.Emit("userConnected", "john_doe") +// +// // Remove the listener when no longer needed +// handle.Remove() package goemitter import ( "sync" ) +// EventEmitter provides event subscription and publishing functionality. +// It is safe for concurrent use thanks to internal synchronization. type EventEmitter struct { - callbacks map[string]map[int]func(args ...interface{}) - onceCallbacks map[string][]func(args ...interface{}) - lock sync.Mutex - counter int + callbacks map[string]map[int]func(args ...interface{}) // Persistent event callbacks indexed by ID + onceCallbacks map[string][]func(args ...interface{}) // One-time event callbacks + lock sync.Mutex // Mutex to ensure thread safety + counter int // Counter for generating unique callback IDs } +// EventHandle represents a handle to a registered event listener. +// It can be used to remove the listener when it's no longer needed. type EventHandle struct { - id int - event string - emitter *EventEmitter + id int // Unique identifier for the callback + event string // Event name + emitter *EventEmitter // Reference to the parent emitter } +// Remove unregisters the event listener associated with this handle. +// After removal, the listener will no longer receive events. func (eh *EventHandle) Remove() { eh.emitter.lock.Lock() defer eh.emitter.lock.Unlock() @@ -26,6 +49,9 @@ func (eh *EventHandle) Remove() { } } +// On registers a new event listener for the specified event. +// It returns an EventHandle that can be used to remove the listener later. +// The callback function can accept any number of arguments passed during event emission. func (e *EventEmitter) On(event string, callback func(args ...interface{})) *EventHandle { e.lock.Lock() defer e.lock.Unlock() @@ -41,6 +67,9 @@ func (e *EventEmitter) On(event string, callback func(args ...interface{})) *Eve } } +// Once registers a one-time event listener for the specified event. +// The listener will be automatically removed after being triggered once. +// Multiple one-time listeners can be registered for the same event. func (e *EventEmitter) Once(event string, callback func(args ...interface{})) { e.lock.Lock() defer e.lock.Unlock() @@ -52,44 +81,55 @@ func (e *EventEmitter) Once(event string, callback func(args ...interface{})) { } } +// Emit triggers an event asynchronously with the provided arguments. +// All registered callbacks for the event will be executed in separate goroutines. +// One-time callbacks are cleared after emission. func (e *EventEmitter) Emit(event string, data ...interface{}) { e.lock.Lock() defer e.lock.Unlock() + // Execute persistent callbacks asynchronously if callbacks, ok := e.callbacks[event]; ok { for _, callback := range callbacks { go callback(data...) } } + // Execute and clear one-time callbacks if onceCallbacks, ok := e.onceCallbacks[event]; ok { for _, callback := range onceCallbacks { go callback(data...) - } e.onceCallbacks[event] = []func(args ...interface{}){} } } +// EmitSync triggers an event synchronously with the provided arguments. +// All registered callbacks for the event will be executed in the current goroutine. +// One-time callbacks are cleared after emission. func (e *EventEmitter) EmitSync(event string, data ...interface{}) { e.lock.Lock() defer e.lock.Unlock() + // Execute persistent callbacks synchronously if callbacks, ok := e.callbacks[event]; ok { for _, callback := range callbacks { callback(data...) } } + // Execute and clear one-time callbacks if onceCallbacks, ok := e.onceCallbacks[event]; ok { for _, callback := range onceCallbacks { callback(data...) - } e.onceCallbacks[event] = []func(args ...interface{}){} } } +// NewEmitter creates and initializes a new EventEmitter instance. +// It initializes the internal maps for storing callbacks and returns +// a pointer to the new instance. func NewEmitter() *EventEmitter { ret := &EventEmitter{} ret.callbacks = make(map[string]map[int]func(args ...interface{}))