From 2349276150cfc39b268e6b13ee5de7936331baaf Mon Sep 17 00:00:00 2001 From: Pierre Mdawar Date: Fri, 23 Aug 2024 21:50:58 +0300 Subject: [PATCH] docs: improve the documentation --- README.md | 97 ++++++++++++++++++++++++++++++++----------------------- map.go | 50 ++++++++++++++-------------- 2 files changed, 82 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 5676e6b..b11e7b2 100644 --- a/README.md +++ b/README.md @@ -14,63 +14,80 @@ go get -u github.com/mdawar/xmap ## Usage +#### New Map + ```go -package main +// Create a map with the default configuration. +m := xmap.New[string, int]() +// Stop the cleanup goroutine and clear the map. +defer m.Stop() +``` -import ( - "context" - "fmt" - "time" +#### Create - "github.com/mdawar/xmap" -) +```go +// Create new entries in the map. +m.Set("a", 1, time.Minute) // Key that expires in 1 minute. +m.Set("b", 2, 0) // Key that never expires (0 TTL). -func main() { - // Create a map with the default configuration. - m := xmap.New[string, int]() - defer m.Stop() // Stop the cleanup goroutine and clear the map. +// Replace a key. +m.Set("a", 3, time.Hour) // Replace key (New value and expiration time). +``` - // Create new entries in the map. - m.Set("a", 1, time.Minute) // Key that expires in 1 minute. - m.Set("b", 2, 0) // Key that never expires (0 TTL). +#### Update - // Replace a key. - m.Set("a", 3, time.Hour) // Replace key (New value and expiration time). +```go +// Update the value without changing the expiration time. +// Reports whether the key was updated (Key exists). +ok := m.Update("b", 4) +``` - // Update the value without changing the expiration time. - // Reports whether the key was updated (Key exists). - ok := m.Update("b", 4) +#### Get - // Get the value if the key exists and has not expired. - // The second return value reports whether the key exists. - value, ok := m.Get("a") +```go +// Get the value if the key exists and has not expired. +// The second return value reports whether the key exists. +value, ok := m.Get("a") + +// Get the value with the expiration time. +// The third return value reports whether the key exists. +value, expiration, ok := m.GetWithExpiration("a") +// If the key never expires, it will have a zero expiration time value. +neverExpires := expiration.IsZero() +``` + +#### Delete - // Get the value with the expiration time. - // The third return value reports whether the key exists. - value, expiration, ok := m.GetWithExpiration("a") - // If the key never expires, it will have a zero expiration time value. - neverExpires := expiration.IsZero() +```go +// Delete a key from the map. +m.Delete("a") - // Length of the map. - total := m.Len() +// Delete all the keys from the map. +m.Clear() +``` - // Delete a key from the map. - m.Delete("a") +#### Length - // Delete all the keys from the map. - m.Clear() +```go +total := m.Len() +``` - // Expired keys are automatically removed at regular intervals. - // Additionally, the removal of expired keys can be manually triggered. - removed := m.RemoveExpired() // Returns the number of removed keys. +#### Iteration - // Iterate over the map entries. - for key, value := range m.All() { - fmt.Println("Key:", key, "-", "Value:", value) - } +```go +for key, value := range m.All() { + fmt.Println("Key:", key, "-", "Value:", value) } ``` +#### Remove Expired Keys + +```go +// Expired keys are automatically removed at regular intervals. +// Additionally, the removal of expired keys can be manually triggered. +removed := m.RemoveExpired() // Returns the number of removed keys. +``` + ## Configuration | Name | Type | Description | diff --git a/map.go b/map.go index 563e95f..6b95c15 100644 --- a/map.go +++ b/map.go @@ -8,13 +8,13 @@ import ( "time" ) -// entry is the value stored internally in the map. +// entry is the value stored internally in the [Map]. type entry[V any] struct { value V // The actual value stored. - exp time.Time // The expiration time. + exp time.Time // The expiration time of the value. } -// Config represents the Map configuration. +// Config represents the [Map] configuration. type Config struct { // CleanupInterval is the interval at which the expired keys are removed. // Default: 5 minutes. @@ -29,7 +29,7 @@ type Config struct { TimeSource Time } -// setDefaults sets the default values for the Map configuration. +// setDefaults sets the default values for the [Map] configuration. func (c *Config) setDefaults() { if c.CleanupInterval == 0 { c.CleanupInterval = 5 * time.Minute @@ -51,12 +51,12 @@ type Map[K comparable, V any] struct { stopped atomic.Int32 // Map stopped flag. } -// New creates a new Map instance with the default configuration. +// New creates a new [Map] instance with the default configuration. func New[K comparable, V any]() *Map[K, V] { return NewWithConfig[K, V](Config{}) } -// NewWithConfig creates a new Map instance with the specified configuration. +// NewWithConfig creates a new [Map] instance with the specified configuration. func NewWithConfig[K comparable, V any](cfg Config) *Map[K, V] { cfg.setDefaults() @@ -72,12 +72,12 @@ func NewWithConfig[K comparable, V any](cfg Config) *Map[K, V] { return m } -// Stop halts the background cleanup goroutine and clears the map. -// It should be called when the map is no longer needed. +// Stop halts the background cleanup goroutine and clears the [Map]. +// It should be called when the [Map] is no longer needed. // // This method is safe to be called multiple times. // -// A stopped map should not be re-used, a new map should be created instead. +// A stopped [Map] should not be re-used, a new [Map] should be created instead. func (m *Map[K, V]) Stop() { if m.stopped.CompareAndSwap(0, 1) { // Stop the cleanup goroutine. @@ -90,19 +90,19 @@ func (m *Map[K, V]) Stop() { } } -// Stopped reports whether the Map is stopped. +// Stopped reports whether the [Map] is stopped. // -// Expired keys are not removed automatically in a stopped map. +// Expired keys are not removed automatically in a stopped [Map]. func (m *Map[K, V]) Stopped() bool { return m.stopped.Load() == 1 } -// Len returns the length of the map. +// Len returns the length of the [Map]. // -// The length of the map is the total number of keys, including the expired +// The length of the [Map] is the total number of keys, including the expired // keys that have not been removed yet. // -// To get the length excluding the number of expired keys, call RemoveExpired +// To get the length excluding the number of expired keys, call [Map.RemoveExpired] // before calling this method. func (m *Map[K, V]) Len() int { m.mu.RLock() @@ -110,7 +110,7 @@ func (m *Map[K, V]) Len() int { return len(m.kv) } -// Set creates or replaces a key/value pair in the map. +// Set creates or replaces a key-value pair in the [Map]. // // A key can be set to never expire with a ttl value of 0. func (m *Map[K, V]) Set(key K, value V, ttl time.Duration) { @@ -141,7 +141,7 @@ func (m *Map[K, V]) Update(key K, value V) bool { // Get returns the value associated with the key. // -// The second bool return value reports whether the key exists in the map. +// The second bool return value reports whether the key exists in the [Map]. func (m *Map[K, V]) Get(key K) (V, bool) { m.mu.RLock() defer m.mu.RUnlock() @@ -156,7 +156,7 @@ func (m *Map[K, V]) Get(key K) (V, bool) { // GetWithExpiration returns the value and expiration time of the key. // -// The third bool return value reports whether the key exists in the map. +// The third bool return value reports whether the key exists in the [Map]. func (m *Map[K, V]) GetWithExpiration(key K) (V, time.Time, bool) { m.mu.RLock() defer m.mu.RUnlock() @@ -169,7 +169,7 @@ func (m *Map[K, V]) GetWithExpiration(key K) (V, time.Time, bool) { return zero, time.Time{}, false } -// All returns an iterator over key-value pairs from the Map. +// All returns an iterator over key-value pairs from the [Map]. // // Only the entries that have not expired are produced during the iteration. // @@ -189,23 +189,23 @@ func (m *Map[K, V]) All() iter.Seq2[K, V] { } } -// Delete removes a key from the map. +// Delete removes a key from the [Map]. func (m *Map[K, V]) Delete(key K) { m.mu.Lock() delete(m.kv, key) m.mu.Unlock() } -// Clear removes all the entries from the map. +// Clear removes all the entries from the [Map]. func (m *Map[K, V]) Clear() { m.mu.Lock() clear(m.kv) m.mu.Unlock() } -// cleanup removes expired keys from the map in an interval. +// cleanup removes expired keys from the [Map] in an interval. // -// The cleanup is stopped by calling Stop. +// The cleanup is stopped by calling [Map.Stop]. func (m *Map[K, V]) cleanup() { ticker := m.time.NewTicker(m.interval) defer ticker.Stop() @@ -229,9 +229,9 @@ func (m *Map[K, V]) CleanupActive() bool { return m.active.Load() == 1 } -// RemoveExpired checks the map keys and removes the expired ones. +// RemoveExpired checks the [Map] keys and removes the expired ones. // -// It returns the number of keys that have expired. +// It returns the number of keys that were removed. func (m *Map[K, V]) RemoveExpired() int { // Expired keys. var expired []K @@ -255,7 +255,7 @@ func (m *Map[K, V]) RemoveExpired() int { return len(expired) } -// expired reports whether an entry has expired. +// expired reports whether an [entry] has expired. func (m *Map[K, V]) expired(entry *entry[V]) bool { return !entry.exp.IsZero() && m.time.Now().After(entry.exp) }