add functions Update/UpdateExpire/GetExpire for package gcache

This commit is contained in:
Jack
2020-08-12 20:13:13 +08:00
parent efa8de34da
commit 7cc1b239d4
4 changed files with 93 additions and 75 deletions

View File

@ -13,42 +13,42 @@ import (
)
// Default cache object.
var cache = New()
var defaultCache = New()
// Set sets cache with <key>-<value> pair, which is expired after <duration>.
// It does not expire if <duration> == 0.
func Set(key interface{}, value interface{}, duration time.Duration) {
cache.Set(key, value, duration)
defaultCache.Set(key, value, duration)
}
// SetVar edit cache with <key>-<value> , but will not change expire.
// If key is not exist return false. Nothing will change.
func SetVar(key interface{}, value interface{}) bool {
return cache.SetVar(key, value)
// Update updates the value of <key> without changing its expiration and returns the old value.
// The returned <exist> value is false if the <key> does not exist in the cache.
func Update(key interface{}, value interface{}) (oldValue interface{}, exist bool) {
return defaultCache.Update(key, value)
}
// SetIfNotExist sets cache with <key>-<value> pair if <key> does not exist in the cache,
// which is expired after <duration>. It does not expire if <duration> == 0.
func SetIfNotExist(key interface{}, value interface{}, duration time.Duration) bool {
return cache.SetIfNotExist(key, value, duration)
return defaultCache.SetIfNotExist(key, value, duration)
}
// Sets batch sets cache with key-value pairs by <data>, which is expired after <duration>.
//
// It does not expire if <duration> == 0.
func Sets(data map[interface{}]interface{}, duration time.Duration) {
cache.Sets(data, duration)
defaultCache.Sets(data, duration)
}
// Get returns the value of <key>.
// It returns nil if it does not exist or its value is nil.
func Get(key interface{}) interface{} {
return cache.Get(key)
return defaultCache.Get(key)
}
// GetVar retrieves and returns the value of <key> as gvar.Var.
func GetVar(key interface{}) *gvar.Var {
return cache.GetVar(key)
return defaultCache.GetVar(key)
}
// GetOrSet returns the value of <key>,
@ -57,14 +57,14 @@ func GetVar(key interface{}) *gvar.Var {
//
// It does not expire if <duration> == 0.
func GetOrSet(key interface{}, value interface{}, duration time.Duration) interface{} {
return cache.GetOrSet(key, value, duration)
return defaultCache.GetOrSet(key, value, duration)
}
// GetOrSetFunc returns the value of <key>, or sets <key> with result of function <f>
// and returns its result if <key> does not exist in the cache. The key-value pair expires
// after <duration>. It does not expire if <duration> == 0.
func GetOrSetFunc(key interface{}, f func() interface{}, duration time.Duration) interface{} {
return cache.GetOrSetFunc(key, f, duration)
return defaultCache.GetOrSetFunc(key, f, duration)
}
// GetOrSetFuncLock returns the value of <key>, or sets <key> with result of function <f>
@ -73,57 +73,59 @@ func GetOrSetFunc(key interface{}, f func() interface{}, duration time.Duration)
//
// Note that the function <f> is executed within writing mutex lock.
func GetOrSetFuncLock(key interface{}, f func() interface{}, duration time.Duration) interface{} {
return cache.GetOrSetFuncLock(key, f, duration)
return defaultCache.GetOrSetFuncLock(key, f, duration)
}
// Contains returns true if <key> exists in the cache, or else returns false.
func Contains(key interface{}) bool {
return cache.Contains(key)
return defaultCache.Contains(key)
}
// Remove deletes the one or more keys from cache, and returns its value.
// If multiple keys are given, it returns the value of the deleted last item.
func Remove(keys ...interface{}) (value interface{}) {
return cache.Remove(keys...)
return defaultCache.Remove(keys...)
}
// Removes deletes <keys> in the cache.
// Deprecated, use Remove instead.
func Removes(keys []interface{}) {
cache.Removes(keys)
defaultCache.Removes(keys)
}
// Data returns a copy of all key-value pairs in the cache as map type.
func Data() map[interface{}]interface{} {
return cache.Data()
return defaultCache.Data()
}
// Keys returns all keys in the cache as slice.
func Keys() []interface{} {
return cache.Keys()
return defaultCache.Keys()
}
// KeyStrings returns all keys in the cache as string slice.
func KeyStrings() []string {
return cache.KeyStrings()
return defaultCache.KeyStrings()
}
// Values returns all values in the cache as slice.
func Values() []interface{} {
return cache.Values()
return defaultCache.Values()
}
// Size returns the size of the cache.
func Size() int {
return cache.Size()
return defaultCache.Size()
}
// GetExpire returns the expire time with given expired duration in milliseconds.
func GetExpire(key interface{}) (int64, bool) {
return cache.GetExpire(key)
// GetExpire retrieves and returns the expiration of <key>.
// It returns -1 if the <key> does not exist in the cache.
func GetExpire(key interface{}) time.Duration {
return defaultCache.GetExpire(key)
}
// SetExpire set cache expired after <duration>.
func SetExpire(key interface{}, duration time.Duration) bool {
return cache.SetExpire(key, duration)
// UpdateExpire updates the expiration of <key> and returns the old expiration duration value.
// It returns -1 if the <key> does not exist in the cache.
func UpdateExpire(key interface{}, duration time.Duration) (oldDuration time.Duration) {
return defaultCache.UpdateExpire(key, duration)
}

View File

@ -64,7 +64,7 @@ type memCache struct {
// Internal cache item.
type memCacheItem struct {
v interface{} // Value.
e int64 // Expire time in milliseconds.
e int64 // Expire timestamp in milliseconds.
}
// Internal event item.
@ -97,7 +97,6 @@ func newMemCache(lruCap ...int) *memCache {
}
// Set sets cache with <key>-<value> pair, which is expired after <duration>.
//
// It does not expire if <duration> == 0.
func (c *memCache) Set(key interface{}, value interface{}, duration time.Duration) {
expireTime := c.getInternalExpire(duration)
@ -113,8 +112,9 @@ func (c *memCache) Set(key interface{}, value interface{}, duration time.Duratio
})
}
// SetVar retrieves and set the value of <key>.
func (c *memCache) SetVar(key interface{}, value interface{}) bool {
// Update updates the value of <key> without changing its expiration and returns the old value.
// The returned <exist> value is false if the <key> does not exist in the cache.
func (c *memCache) Update(key interface{}, value interface{}) (oldValue interface{}, exist bool) {
c.dataMu.Lock()
defer c.dataMu.Unlock()
if item, ok := c.data[key]; ok {
@ -122,21 +122,18 @@ func (c *memCache) SetVar(key interface{}, value interface{}) bool {
v: value,
e: item.e,
}
return true
return item.v, true
}
return false
return nil, false
}
// SetExpire retrieves and set the value of <key>.
func (c *memCache) SetExpire(key interface{}, duration time.Duration) bool {
// UpdateExpire updates the expiration of <key> and returns the old expiration duration value.
// It returns -1 if the <key> does not exist in the cache.
func (c *memCache) UpdateExpire(key interface{}, duration time.Duration) (oldDuration time.Duration) {
newExpireTime := c.getInternalExpire(duration)
c.dataMu.Lock()
defer c.dataMu.Unlock()
if item, ok := c.data[key]; ok {
c.eventList.PushBack(&memCacheEvent{
k: key,
e: gtime.TimestampMilli() - 1000,
})
newExpireTime := c.getInternalExpire(duration)
c.data[key] = memCacheItem{
v: item.v,
e: newExpireTime,
@ -145,18 +142,20 @@ func (c *memCache) SetExpire(key interface{}, duration time.Duration) bool {
k: key,
e: newExpireTime,
})
return true
return time.Duration(item.e-gtime.TimestampMilli()) * time.Millisecond
}
return false
return -1
}
func (c *memCache) GetExpire(key interface{}) (int64, bool) {
// GetExpire retrieves and returns the expiration of <key>.
// It returns -1 if the <key> does not exist in the cache.
func (c *memCache) GetExpire(key interface{}) time.Duration {
c.dataMu.RLock()
defer c.dataMu.RUnlock()
if item, ok := c.data[key]; ok {
return item.e, true
return time.Duration(item.e-gtime.TimestampMilli()) * time.Millisecond
}
return 0, false
return -1
}
// doSetWithLockCheck sets cache with <key>-<value> pair if <key> does not exist in the

View File

@ -15,15 +15,15 @@ import (
)
var (
cache = gcache.New()
cacheLru = gcache.New(10000)
localCache = gcache.New()
localCacheLru = gcache.New(10000)
)
func Benchmark_CacheSet(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
i := 0
for pb.Next() {
cache.Set(i, i, 0)
localCache.Set(i, i, 0)
i++
}
})
@ -33,7 +33,7 @@ func Benchmark_CacheGet(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
i := 0
for pb.Next() {
cache.Get(i)
localCache.Get(i)
i++
}
})
@ -43,7 +43,7 @@ func Benchmark_CacheRemove(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
i := 0
for pb.Next() {
cache.Remove(i)
localCache.Remove(i)
i++
}
})
@ -53,7 +53,7 @@ func Benchmark_CacheLruSet(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
i := 0
for pb.Next() {
cacheLru.Set(i, i, 0)
localCacheLru.Set(i, i, 0)
i++
}
})
@ -63,7 +63,7 @@ func Benchmark_CacheLruGet(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
i := 0
for pb.Next() {
cacheLru.Get(i)
localCacheLru.Get(i)
i++
}
})
@ -73,7 +73,7 @@ func Benchmark_CacheLruRemove(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
i := 0
for pb.Next() {
cacheLru.Remove(i)
localCacheLru.Remove(i)
i++
}
})

View File

@ -9,9 +9,7 @@
package gcache_test
import (
"fmt"
"github.com/gogf/gf/os/glog"
"github.com/gogf/gf/util/grand"
"github.com/gogf/gf/util/guid"
"testing"
"time"
@ -76,32 +74,51 @@ func TestCache_Set_Expire(t *testing.T) {
})
}
func TestCache_SetVar(t *testing.T) {
func TestCache_Update_GetExpire(t *testing.T) {
// gcache
gtest.C(t, func(t *gtest.T) {
key := guid.S()
gcache.Set(key, 11, 3*time.Second)
oldExpire1 := gcache.GetExpire(key)
gcache.Update(key, 12)
oldExpire2 := gcache.GetExpire(key)
t.Assert(gcache.GetVar(key), 12)
t.Assert(oldExpire1, oldExpire2)
})
// gcache.Cache
gtest.C(t, func(t *gtest.T) {
cache := gcache.New()
cache.Set(1, 11, 3*time.Second)
expireBefore, _ := cache.GetExpire(1)
cache.SetVar(1, 12)
expireAfter, _ := cache.GetExpire(1)
oldExpire1 := cache.GetExpire(1)
cache.Update(1, 12)
oldExpire2 := cache.GetExpire(1)
t.Assert(cache.GetVar(1), 12)
t.Assert(expireBefore, expireAfter)
t.Assert(oldExpire1, oldExpire2)
})
}
func BenchmarkMemCache_GetSetExpire(b *testing.B) {
cache := gcache.New()
cache.Set(1, 11, 3*time.Second)
if expire, ok := cache.GetExpire(1); ok {
glog.Println(expire)
}
for i := 0; i < b.N; i++ {
r := time.Duration(grand.N(5, 10))
cache.SetExpire(1, r*time.Second)
//cache.SetExpire(1, 7*time.Second)
if _, ok := cache.GetExpire(1); !ok {
panic(fmt.Sprintf("[ERROR] %s", "GetExpire error"))
}
}
func TestCache_UpdateExpire(t *testing.T) {
// gcache
gtest.C(t, func(t *gtest.T) {
key := guid.S()
gcache.Set(key, 11, 3*time.Second)
defer gcache.Remove(key)
oldExpire := gcache.GetExpire(key)
newExpire := 10 * time.Second
gcache.UpdateExpire(key, newExpire)
t.AssertNE(gcache.GetExpire(key), oldExpire)
t.Assert(gcache.GetExpire(key), newExpire)
})
// gcache.Cache
gtest.C(t, func(t *gtest.T) {
cache := gcache.New()
cache.Set(1, 11, 3*time.Second)
oldExpire := cache.GetExpire(1)
newExpire := 10 * time.Second
cache.UpdateExpire(1, newExpire)
t.AssertNE(cache.GetExpire(1), oldExpire)
t.Assert(cache.GetExpire(1), newExpire)
})
}
func TestCache_Keys_Values(t *testing.T) {