summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-cache/v2/ttl.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/codeberg.org/gruf/go-cache/v2/ttl.go')
-rw-r--r--vendor/codeberg.org/gruf/go-cache/v2/ttl.go121
1 files changed, 49 insertions, 72 deletions
diff --git a/vendor/codeberg.org/gruf/go-cache/v2/ttl.go b/vendor/codeberg.org/gruf/go-cache/v2/ttl.go
index 42f28b53b..a5b6637b2 100644
--- a/vendor/codeberg.org/gruf/go-cache/v2/ttl.go
+++ b/vendor/codeberg.org/gruf/go-cache/v2/ttl.go
@@ -1,11 +1,8 @@
package cache
import (
- "context"
"sync"
"time"
-
- "codeberg.org/gruf/go-runners"
)
// TTLCache is the underlying Cache implementation, providing both the base
@@ -16,11 +13,11 @@ type TTLCache[Key comparable, Value any] struct {
evict Hook[Key, Value] // the evict hook is called when an item is evicted from the cache, includes manual delete
invalid Hook[Key, Value] // the invalidate hook is called when an item's data in the cache is invalidated
ttl time.Duration // ttl is the item TTL
- svc runners.Service // svc manages running of the cache eviction routine
+ stop func() // stop is the cancel function for the scheduled eviction routine
mu sync.Mutex // mu protects TTLCache for concurrent access
}
-// Init performs Cache initialization, this MUST be called.
+// Init performs Cache initialization. MUST be called.
func (c *TTLCache[K, V]) Init() {
c.cache = make(map[K](*entry[V]), 100)
c.evict = emptyHook[K, V]
@@ -28,68 +25,48 @@ func (c *TTLCache[K, V]) Init() {
c.ttl = time.Minute * 5
}
-func (c *TTLCache[K, V]) Start(freq time.Duration) bool {
+func (c *TTLCache[K, V]) Start(freq time.Duration) (ok bool) {
// Nothing to start
if freq <= 0 {
return false
}
- // Track state of starting
- done := make(chan struct{})
- started := false
-
- go func() {
- ran := c.svc.Run(func(ctx context.Context) {
- // Successfully started
- started = true
- close(done)
+ // Safely start
+ c.mu.Lock()
- // start routine
- c.run(ctx, freq)
- })
+ if ok = c.stop == nil; ok {
+ // Not yet running, schedule us
+ c.stop = schedule(c.sweep, freq)
+ }
- // failed to start
- if !ran {
- close(done)
- }
- }()
+ // Done with lock
+ c.mu.Unlock()
- <-done
- return started
+ return
}
-func (c *TTLCache[K, V]) Stop() bool {
- return c.svc.Stop()
-}
+func (c *TTLCache[K, V]) Stop() (ok bool) {
+ // Safely stop
+ c.mu.Lock()
-func (c *TTLCache[K, V]) run(ctx context.Context, freq time.Duration) {
- t := time.NewTimer(freq)
- for {
- select {
- // we got stopped
- case <-ctx.Done():
- if !t.Stop() {
- <-t.C
- }
- return
-
- // next tick
- case <-t.C:
- c.sweep()
- t.Reset(freq)
- }
+ if ok = c.stop != nil; ok {
+ // We're running, cancel evicts
+ c.stop()
+ c.stop = nil
}
+
+ // Done with lock
+ c.mu.Unlock()
+
+ return
}
// sweep attempts to evict expired items (with callback!) from cache.
-func (c *TTLCache[K, V]) sweep() {
+func (c *TTLCache[K, V]) sweep(now time.Time) {
// Lock and defer unlock (in case of hook panic)
c.mu.Lock()
defer c.mu.Unlock()
- // Fetch current time for TTL check
- now := time.Now()
-
// Sweep the cache for old items!
for key, item := range c.cache {
if now.After(item.expiry) {
@@ -116,9 +93,9 @@ func (c *TTLCache[K, V]) SetEvictionCallback(hook Hook[K, V]) {
}
// Safely set evict hook
- c.Lock()
+ c.mu.Lock()
c.evict = hook
- c.Unlock()
+ c.mu.Unlock()
}
func (c *TTLCache[K, V]) SetInvalidateCallback(hook Hook[K, V]) {
@@ -128,14 +105,14 @@ func (c *TTLCache[K, V]) SetInvalidateCallback(hook Hook[K, V]) {
}
// Safely set invalidate hook
- c.Lock()
+ c.mu.Lock()
c.invalid = hook
- c.Unlock()
+ c.mu.Unlock()
}
func (c *TTLCache[K, V]) SetTTL(ttl time.Duration, update bool) {
// Safely update TTL
- c.Lock()
+ c.mu.Lock()
diff := ttl - c.ttl
c.ttl = ttl
@@ -147,13 +124,13 @@ func (c *TTLCache[K, V]) SetTTL(ttl time.Duration, update bool) {
}
// We're done
- c.Unlock()
+ c.mu.Unlock()
}
func (c *TTLCache[K, V]) Get(key K) (V, bool) {
- c.Lock()
+ c.mu.Lock()
value, ok := c.GetUnsafe(key)
- c.Unlock()
+ c.mu.Unlock()
return value, ok
}
@@ -169,9 +146,9 @@ func (c *TTLCache[K, V]) GetUnsafe(key K) (V, bool) {
}
func (c *TTLCache[K, V]) Put(key K, value V) bool {
- c.Lock()
+ c.mu.Lock()
success := c.PutUnsafe(key, value)
- c.Unlock()
+ c.mu.Unlock()
return success
}
@@ -192,8 +169,8 @@ func (c *TTLCache[K, V]) PutUnsafe(key K, value V) bool {
}
func (c *TTLCache[K, V]) Set(key K, value V) {
- c.Lock()
- defer c.Unlock() // defer in case of hook panic
+ c.mu.Lock()
+ defer c.mu.Unlock() // defer in case of hook panic
c.SetUnsafe(key, value)
}
@@ -215,9 +192,9 @@ func (c *TTLCache[K, V]) SetUnsafe(key K, value V) {
}
func (c *TTLCache[K, V]) CAS(key K, cmp V, swp V) bool {
- c.Lock()
+ c.mu.Lock()
ok := c.CASUnsafe(key, cmp, swp)
- c.Unlock()
+ c.mu.Unlock()
return ok
}
@@ -240,9 +217,9 @@ func (c *TTLCache[K, V]) CASUnsafe(key K, cmp V, swp V) bool {
}
func (c *TTLCache[K, V]) Swap(key K, swp V) V {
- c.Lock()
+ c.mu.Lock()
old := c.SwapUnsafe(key, swp)
- c.Unlock()
+ c.mu.Unlock()
return old
}
@@ -267,9 +244,9 @@ func (c *TTLCache[K, V]) SwapUnsafe(key K, swp V) V {
}
func (c *TTLCache[K, V]) Has(key K) bool {
- c.Lock()
+ c.mu.Lock()
ok := c.HasUnsafe(key)
- c.Unlock()
+ c.mu.Unlock()
return ok
}
@@ -280,8 +257,8 @@ func (c *TTLCache[K, V]) HasUnsafe(key K) bool {
}
func (c *TTLCache[K, V]) Invalidate(key K) bool {
- c.Lock()
- defer c.Unlock()
+ c.mu.Lock()
+ defer c.mu.Unlock()
return c.InvalidateUnsafe(key)
}
@@ -300,8 +277,8 @@ func (c *TTLCache[K, V]) InvalidateUnsafe(key K) bool {
}
func (c *TTLCache[K, V]) Clear() {
- c.Lock()
- defer c.Unlock()
+ c.mu.Lock()
+ defer c.mu.Unlock()
c.ClearUnsafe()
}
@@ -314,9 +291,9 @@ func (c *TTLCache[K, V]) ClearUnsafe() {
}
func (c *TTLCache[K, V]) Size() int {
- c.Lock()
+ c.mu.Lock()
sz := c.SizeUnsafe()
- c.Unlock()
+ c.mu.Unlock()
return sz
}