|
@@ -82,12 +82,7 @@ func (c *Cache) Del(key string) {
|
|
}
|
|
}
|
|
|
|
|
|
func (c *Cache) Get(key string) (interface{}, bool) {
|
|
func (c *Cache) Get(key string) (interface{}, bool) {
|
|
- c.lock.Lock()
|
|
|
|
- value, ok := c.data[key]
|
|
|
|
- if ok {
|
|
|
|
- c.lruCache.add(key)
|
|
|
|
- }
|
|
|
|
- c.lock.Unlock()
|
|
|
|
|
|
+ value, ok := c.doGet(key)
|
|
if ok {
|
|
if ok {
|
|
c.stats.IncrementHit()
|
|
c.stats.IncrementHit()
|
|
} else {
|
|
} else {
|
|
@@ -113,12 +108,25 @@ func (c *Cache) Set(key string, value interface{}) {
|
|
}
|
|
}
|
|
|
|
|
|
func (c *Cache) Take(key string, fetch func() (interface{}, error)) (interface{}, error) {
|
|
func (c *Cache) Take(key string, fetch func() (interface{}, error)) (interface{}, error) {
|
|
- val, fresh, err := c.barrier.DoEx(key, func() (interface{}, error) {
|
|
|
|
|
|
+ if val, ok := c.doGet(key); ok {
|
|
|
|
+ c.stats.IncrementHit()
|
|
|
|
+ return val, nil
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var fresh bool
|
|
|
|
+ val, err := c.barrier.Do(key, func() (interface{}, error) {
|
|
|
|
+ // because O(1) on map search in memory, and fetch is an IO query
|
|
|
|
+ // so we do double check, cache might be taken by another call
|
|
|
|
+ if val, ok := c.doGet(key); ok {
|
|
|
|
+ return val, nil
|
|
|
|
+ }
|
|
|
|
+
|
|
v, e := fetch()
|
|
v, e := fetch()
|
|
if e != nil {
|
|
if e != nil {
|
|
return nil, e
|
|
return nil, e
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ fresh = true
|
|
c.Set(key, v)
|
|
c.Set(key, v)
|
|
return v, nil
|
|
return v, nil
|
|
})
|
|
})
|
|
@@ -137,6 +145,18 @@ func (c *Cache) Take(key string, fetch func() (interface{}, error)) (interface{}
|
|
return val, nil
|
|
return val, nil
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func (c *Cache) doGet(key string) (interface{}, bool) {
|
|
|
|
+ c.lock.Lock()
|
|
|
|
+ defer c.lock.Unlock()
|
|
|
|
+
|
|
|
|
+ value, ok := c.data[key]
|
|
|
|
+ if ok {
|
|
|
|
+ c.lruCache.add(key)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return value, ok
|
|
|
|
+}
|
|
|
|
+
|
|
func (c *Cache) onEvict(key string) {
|
|
func (c *Cache) onEvict(key string) {
|
|
// already locked
|
|
// already locked
|
|
delete(c.data, key)
|
|
delete(c.data, key)
|