mirror of
https://github.com/geektutu/7days-golang.git
synced 2024-04-21 12:32:11 +00:00
80 lines
1.6 KiB
Go
80 lines
1.6 KiB
Go
package lru
|
|
|
|
import "container/list"
|
|
|
|
// Cache is a LRU cache. It is not safe for concurrent access.
|
|
type Cache struct {
|
|
maxBytes int64
|
|
nbytes int64
|
|
ll *list.List
|
|
cache map[string]*list.Element
|
|
// optional and executed when an entry is purged.
|
|
OnEvicted func(key string, value Value)
|
|
}
|
|
|
|
type entry struct {
|
|
key string
|
|
value Value
|
|
}
|
|
|
|
// Value use Len to count how many bytes it takes
|
|
type Value interface {
|
|
Len() int
|
|
}
|
|
|
|
// New is the Constructor of Cache
|
|
func New(maxBytes int64, onEvicted func(string, Value)) *Cache {
|
|
return &Cache{
|
|
maxBytes: maxBytes,
|
|
ll: list.New(),
|
|
cache: make(map[string]*list.Element),
|
|
OnEvicted: onEvicted,
|
|
}
|
|
}
|
|
|
|
// Add adds a value to the cache.
|
|
func (c *Cache) Add(key string, value Value) {
|
|
if ele, ok := c.cache[key]; ok {
|
|
c.ll.MoveToFront(ele)
|
|
kv := ele.Value.(*entry)
|
|
kv.value = value
|
|
return
|
|
}
|
|
ele := c.ll.PushFront(&entry{key, value})
|
|
c.cache[key] = ele
|
|
c.nbytes += int64(len(key)) + int64(value.Len())
|
|
|
|
for c.maxBytes != 0 && c.maxBytes < c.nbytes {
|
|
c.RemoveOldest()
|
|
}
|
|
}
|
|
|
|
// Get look ups a key's value
|
|
func (c *Cache) Get(key string) (value Value, ok bool) {
|
|
if ele, ok := c.cache[key]; ok {
|
|
c.ll.MoveToFront(ele)
|
|
kv := ele.Value.(*entry)
|
|
return kv.value, true
|
|
}
|
|
return
|
|
}
|
|
|
|
// RemoveOldest removes the oldest item
|
|
func (c *Cache) RemoveOldest() {
|
|
ele := c.ll.Back()
|
|
if ele != nil {
|
|
c.ll.Remove(ele)
|
|
kv := ele.Value.(*entry)
|
|
delete(c.cache, kv.key)
|
|
c.nbytes -= int64(len(kv.key)) + int64(kv.value.Len())
|
|
if c.OnEvicted != nil {
|
|
c.OnEvicted(kv.key, kv.value)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Len the number of cache entries
|
|
func (c *Cache) Len() int {
|
|
return c.ll.Len()
|
|
}
|