Files
archived-rttys/cache/cache.go
T
Jianhui Zhao bfefcdb0bd perf: replace interface{} with any
Signed-off-by: Jianhui Zhao <zhaojh329@gmail.com>
2025-05-28 14:25:18 +08:00

112 lines
1.7 KiB
Go

package cache
import (
"runtime"
"sync"
"time"
)
type Item struct {
value any
expiration int64
}
type Cache struct {
items sync.Map
defaultExpiration time.Duration
gcInterval time.Duration
stop chan struct{}
}
// Delete all expired items from the cache.
func (c *Cache) DeleteExpired() {
now := time.Now().UnixNano()
c.items.Range(func(key, value any) bool {
if value := value.(*Item); value.expiration > 0 && now > value.expiration {
c.items.Delete(key)
}
return true
})
}
func (c *Cache) gcLoop() {
ticker := time.NewTicker(c.gcInterval)
for {
select {
case <-ticker.C:
c.DeleteExpired()
case <-c.stop:
ticker.Stop()
return
}
}
}
func New(defaultExpiration, gcInterval time.Duration) *Cache {
c := &Cache{
defaultExpiration: defaultExpiration,
gcInterval: gcInterval,
stop: make(chan struct{}),
}
go c.gcLoop()
runtime.SetFinalizer(c, func(c *Cache) {
c.stop <- struct{}{}
})
return c
}
func (c *Cache) Active(key any, d time.Duration) {
v, ok := c.items.Load(key)
if ok {
v := v.(*Item)
var e int64
if d == 0 {
d = c.defaultExpiration
}
if d > 0 {
e = time.Now().Add(d).UnixNano()
}
v.expiration = e
}
}
func (c *Cache) Set(key, value any, d time.Duration) {
var e int64
if d == 0 {
d = c.defaultExpiration
}
if d > 0 {
e = time.Now().Add(d).UnixNano()
}
c.items.Store(key, &Item{value, e})
}
func (c *Cache) Get(key any) (any, bool) {
v, ok := c.items.Load(key)
if ok {
v := v.(*Item)
return v.value, true
}
return nil, false
}
func (c *Cache) Del(key any) {
c.items.Delete(key)
}
func (c *Cache) Have(key string) bool {
_, ok := c.items.Load(key)
return ok
}