109 lines
2 KiB
Go
109 lines
2 KiB
Go
package utils
|
|
|
|
import (
|
|
"github.com/hashicorp/golang-lru/v2"
|
|
"sync"
|
|
"sync/atomic"
|
|
)
|
|
|
|
type Cache[K comparable, T any] interface {
|
|
Get(key K) (value T, ok bool)
|
|
Set(key K, value T)
|
|
Delete(key K)
|
|
Clear()
|
|
Stats() (hits, misses uint64)
|
|
}
|
|
|
|
type LRUCache[K comparable, T any] struct {
|
|
values atomic.Pointer[lru.Cache[K, T]]
|
|
hits, misses atomic.Uint64
|
|
size int
|
|
}
|
|
|
|
func NewLRUCache[K comparable, T any](size int) *LRUCache[K, T] {
|
|
c := &LRUCache[K, T]{
|
|
size: size,
|
|
}
|
|
c.Clear()
|
|
return c
|
|
}
|
|
|
|
func (c *LRUCache[K, T]) Get(key K) (value T, ok bool) {
|
|
if value, ok = c.values.Load().Get(key); ok {
|
|
c.hits.Add(1)
|
|
return value, true
|
|
} else {
|
|
c.misses.Add(1)
|
|
return value, false
|
|
}
|
|
}
|
|
|
|
func (c *LRUCache[K, T]) Set(key K, value T) {
|
|
c.values.Load().Add(key, value)
|
|
}
|
|
|
|
func (c *LRUCache[K, T]) Delete(key K) {
|
|
c.values.Load().Remove(key)
|
|
}
|
|
|
|
func (c *LRUCache[K, T]) Clear() {
|
|
cache, err := lru.New[K, T](c.size)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
c.values.Store(cache)
|
|
}
|
|
|
|
func (c *LRUCache[K, T]) Stats() (hits, misses uint64) {
|
|
return c.hits.Load(), c.misses.Load()
|
|
}
|
|
|
|
type MapCache[K comparable, T any] struct {
|
|
lock sync.RWMutex
|
|
values map[K]T
|
|
hits, misses atomic.Uint64
|
|
size int
|
|
}
|
|
|
|
func NewMapCache[K comparable, T any](preAllocateSize int) *MapCache[K, T] {
|
|
return &MapCache[K, T]{
|
|
values: make(map[K]T, preAllocateSize),
|
|
size: preAllocateSize,
|
|
}
|
|
}
|
|
|
|
func (m *MapCache[K, T]) Get(key K) (value T, ok bool) {
|
|
m.lock.RLock()
|
|
defer m.lock.RUnlock()
|
|
value, ok = m.values[key]
|
|
if ok {
|
|
m.hits.Add(1)
|
|
} else {
|
|
m.misses.Add(1)
|
|
}
|
|
return value, ok
|
|
}
|
|
|
|
func (m *MapCache[K, T]) Set(key K, value T) {
|
|
m.lock.Lock()
|
|
defer m.lock.Unlock()
|
|
m.values[key] = value
|
|
}
|
|
|
|
func (m *MapCache[K, T]) Delete(key K) {
|
|
m.lock.Lock()
|
|
defer m.lock.Unlock()
|
|
delete(m.values, key)
|
|
}
|
|
|
|
func (m *MapCache[K, T]) Clear() {
|
|
m.lock.Lock()
|
|
defer m.lock.Unlock()
|
|
m.values = make(map[K]T, m.size)
|
|
}
|
|
|
|
func (m *MapCache[K, T]) Stats() (hits, misses uint64) {
|
|
m.lock.Lock()
|
|
defer m.lock.Unlock()
|
|
return m.hits.Load(), m.misses.Load()
|
|
}
|