You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
synctv/utils/syncCache/cache.go

123 lines
2.6 KiB
Go

2 years ago
package synccache
import (
"time"
"github.com/zijiren233/gencontainer/rwmap"
)
type SyncCache[K comparable, V any] struct {
cache rwmap.RWMap[K, *Entry[V]]
deletedCallback func(v V)
ticker *time.Ticker
}
type SyncCacheConfig[K comparable, V any] func(sc *SyncCache[K, V])
func WithDeletedCallback[K comparable, V any](callback func(v V)) SyncCacheConfig[K, V] {
return func(sc *SyncCache[K, V]) {
sc.deletedCallback = callback
}
2 years ago
}
func NewSyncCache[K comparable, V any](trimTime time.Duration, conf ...SyncCacheConfig[K, V]) *SyncCache[K, V] {
2 years ago
sc := &SyncCache[K, V]{
ticker: time.NewTicker(trimTime),
}
for _, c := range conf {
c(sc)
}
2 years ago
go func() {
for range sc.ticker.C {
sc.trim()
}
}()
return sc
}
func (sc *SyncCache[K, V]) Releases() {
sc.ticker.Stop()
sc.cache.Clear()
}
func (sc *SyncCache[K, V]) trim() {
sc.cache.Range(func(key K, value *Entry[V]) bool {
2 years ago
if value.IsExpired() {
sc.cache.CompareAndDelete(key, value)
if sc.deletedCallback != nil {
sc.deletedCallback(value.value)
}
2 years ago
}
return true
})
}
func (sc *SyncCache[K, V]) Store(key K, value V, expire time.Duration) {
sc.LoadOrStore(key, value, expire)
}
func (sc *SyncCache[K, V]) Load(key K) (value *Entry[V], loaded bool) {
2 years ago
e, ok := sc.cache.Load(key)
if ok && !e.IsExpired() {
return e, ok
2 years ago
}
return
}
func (sc *SyncCache[K, V]) LoadOrStore(key K, value V, expire time.Duration) (actual *Entry[V], loaded bool) {
e, loaded := sc.cache.LoadOrStore(key, NewEntry[V](value, expire))
2 years ago
if e.IsExpired() {
e = NewEntry[V](value, expire)
sc.cache.Store(key, e)
return e, false
2 years ago
}
return e, loaded
2 years ago
}
func (sc *SyncCache[K, V]) AddExpiration(key K, d time.Duration) {
e, ok := sc.cache.Load(key)
if ok {
e.AddExpiration(d)
}
}
func (sc *SyncCache[K, V]) SetExpiration(key K, t time.Time) {
e, ok := sc.cache.Load(key)
if ok {
e.SetExpiration(t)
}
}
2 years ago
func (sc *SyncCache[K, V]) Delete(key K) {
sc.LoadAndDelete(key)
}
func (sc *SyncCache[K, V]) LoadAndDelete(key K) (value *Entry[V], loaded bool) {
2 years ago
e, loaded := sc.cache.LoadAndDelete(key)
if loaded && !e.IsExpired() {
return e, loaded
2 years ago
}
return
}
func (sc *SyncCache[K, V]) CompareAndDelete(key K, oldEntry *Entry[V]) (success bool) {
b := sc.cache.CompareAndDelete(key, oldEntry)
if b && sc.deletedCallback != nil {
sc.deletedCallback(oldEntry.value)
}
return b
}
2 years ago
func (sc *SyncCache[K, V]) Clear() {
sc.cache.Clear()
}
func (sc *SyncCache[K, V]) Range(f func(key K, value *Entry[V]) bool) {
sc.cache.Range(func(key K, value *Entry[V]) bool {
if !value.IsExpired() {
return f(key, value)
}
return true
})
}