Files
cgrates/cache2go/cache.go
Radu Ioan Fericean e4ed91297d as dirs
2012-09-20 11:50:36 +03:00

118 lines
2.4 KiB
Go

//Simple caching library with expiration capabilities
package cache2go
import (
"errors"
"sync"
"time"
)
type expiringCacheEntry interface {
XCache(key string, expire time.Duration, value expiringCacheEntry)
timer() *time.Timer
KeepAlive()
}
// Structure that must be embeded in the objectst that must be cached with expiration.
// If the expiration is not needed this can be ignored
type XEntry struct {
sync.Mutex
key string
keepAlive bool
expireDuration time.Duration
t *time.Timer
}
var (
xcache = make(map[string]expiringCacheEntry)
xMux sync.RWMutex
cache = make(map[string]interface{})
mux sync.RWMutex
)
// The main function to cache with expiration
func (xe *XEntry) XCache(key string, expire time.Duration, value expiringCacheEntry) {
xe.keepAlive = true
xe.key = key
xe.expireDuration = expire
xMux.Lock()
xcache[key] = value
xMux.Unlock()
go xe.expire()
}
// The internal mechanism for expiartion
func (xe *XEntry) expire() {
for xe.keepAlive {
xe.Lock()
xe.keepAlive = false
xe.Unlock()
xe.t = time.NewTimer(xe.expireDuration)
<-xe.t.C
if !xe.keepAlive {
xMux.Lock()
delete(xcache, xe.key)
xMux.Unlock()
}
}
}
// Getter for the timer
func (xe *XEntry) timer() *time.Timer {
return xe.t
}
// Mark entry to be kept another expirationDuration period
func (xe *XEntry) KeepAlive() {
xe.Lock()
defer xe.Unlock()
xe.keepAlive = true
}
// Get an entry from the expiration cache and mark it for keeping alive
func GetXCached(key string) (ece expiringCacheEntry, err error) {
xMux.RLock()
defer xMux.RUnlock()
if r, ok := xcache[key]; ok {
r.KeepAlive()
return r, nil
}
return nil, errors.New("not found")
}
// The function to be used to cache a key/value pair when expiration is not needed
func Cache(key string, value interface{}) {
mux.Lock()
defer mux.Unlock()
cache[key] = value
}
// The function to extract a value for a key that never expire
func GetCached(key string) (v interface{}, err error) {
mux.RLock()
defer mux.RUnlock()
if r, ok := cache[key]; ok {
return r, nil
}
return nil, errors.New("not found")
}
// Delete all keys from expiraton cache
func XFlush() {
xMux.Lock()
defer xMux.Unlock()
for _, v := range xcache {
if v.timer() != nil {
v.timer().Stop()
}
}
xcache = make(map[string]expiringCacheEntry)
}
// Delete all keys from cache
func Flush() {
mux.Lock()
defer mux.Unlock()
cache = make(map[string]interface{})
}