diff --git a/cowmap.go b/cowmap.go index 4bc2832..823799c 100644 --- a/cowmap.go +++ b/cowmap.go @@ -13,6 +13,7 @@ type CowMap struct { readable atomic.Value } +// NewCowMap creates a new CowMap instance func NewCowMap() *CowMap { m := make(tmap) c := &CowMap{} @@ -20,7 +21,8 @@ func NewCowMap() *CowMap { return c } -// clone create a copy of the map +// clone creates a copy of the map by iterating over the original map +// and copying its key-value pairs to the new map func (c *CowMap) clone() tmap { m := make(tmap) for k, v := range c.readable.Load().(tmap) { @@ -29,30 +31,32 @@ func (c *CowMap) clone() tmap { return m } -// Load returns the value stored in the map for a key, or nil if no -// value is present. -// The ok result indicates whether value was found in the map. +// Load returns the value stored in the map for a given key, +// or nil if the key is not present. +// The ok result indicates whether the value was found in the map. func (c *CowMap) Load(key any) (value any, ok bool) { value, ok = c.readable.Load().(tmap)[key] return } -// Len returns how many values stored in the map. +// Len returns the number of key-value pairs stored in the map func (c *CowMap) Len() int { return len(c.readable.Load().(tmap)) } -// Store sets the value for a key. +// Store sets the value for a given key by creating a new copy of the map +// and adding the new key-value pair to it func (c *CowMap) Store(key, value any) { c.mu.Lock() defer c.mu.Unlock() - copy := c.clone() - copy[key] = value - c.readable.Store(copy) + copy := c.clone() // create a copy of the map + copy[key] = value // add the new key-value pair to the copy + c.readable.Store(copy) // update the atomic value with the new copy } -// Delete deletes the value for a key. +// Delete removes a key-value pair from the map by creating a new copy of the map +// and deleting the specified key from it func (c *CowMap) Delete(key any) { c.mu.Lock() defer c.mu.Unlock() @@ -63,8 +67,8 @@ func (c *CowMap) Delete(key any) { c.readable.Store(copy) } -// Range calls f sequentially for each key and value present in the map. -// If f returns false, range stops the iteration. +// Range calls the provided function for each key-value pair in the map, +// stopping the iteration if the function returns false func (c *CowMap) Range(f func(key, value any) bool) { for k, v := range c.readable.Load().(tmap) { if !f(k, v) { diff --git a/errors.go b/errors.go index 9483f67..cfa18a7 100644 --- a/errors.go +++ b/errors.go @@ -19,6 +19,8 @@ func (e err) Error() string { return e.Msg } +// Global variables that represent common errors that may be +// returned by the eventbus functions. var ( ErrHandlerIsNotFunc = err{Code: 10000, Msg: "handler is not a function"} ErrHandlerParamNum = err{Code: 10001, Msg: "the number of parameters of the handler must be two"} diff --git a/eventbus.go b/eventbus.go index 86fd4bf..ad05a09 100644 --- a/eventbus.go +++ b/eventbus.go @@ -5,7 +5,7 @@ import ( "sync" ) -// channel is the box of a topic and handlers. a topic corresponds to a channel +// channel is a struct representing a topic and its associated handlers. type channel struct { sync.RWMutex bufferSize int @@ -16,7 +16,9 @@ type channel struct { stopCh chan any } -// newChannel create a channle for a topic +// newChannel creates a new channel with a specified topic and buffer size. +// It initializes the handlers map with NewCowMap function and +// starts a goroutine c.loop() to continuously listen to messages in the channel. func newChannel(topic string, bufferSize int) *channel { var ch chan any if bufferSize <= 0 { @@ -35,7 +37,9 @@ func newChannel(topic string, bufferSize int) *channel { return c } -// loop loops forever, receiving published message from the channel, transfer payload to subscriber by calling handlers +// loop listens to the channel and calls handlers with payload. +// It receives messages from the channel and then iterates over the handlers +// in the handlers map to call them with the payload. func (c *channel) loop() { topic := reflect.ValueOf(c.topic) for { @@ -48,6 +52,9 @@ func (c *channel) loop() { typ := handler.Type() if param == nil { + // If the parameter passed to the handler is nil, + // it initializes a new payload element based on the + // type of the second parameter of the handler using the reflect package. payload = reflect.New(typ.In(1)).Elem() } else { payload = reflect.ValueOf(param)