package main
import (
"container/list"
"sync"
)
type LRUCache struct {
mu sync.RWMutex
capacity int
items map[string]*list.Element
evictList *list.List
}
type entry struct {
key string
value []byte
}
func NewLRUCache(capacity int) *LRUCache {
return &LRUCache{
capacity: capacity,
items: make(map[string]*list.Element),
evictList: list.New(),
}
}
func (c *LRUCache) Get(key string) ([]byte, bool) {
c.mu.Lock()
defer c.mu.Unlock()
if elem, ok := c.items[key]; ok {
c.evictList.MoveToFront(elem)
return elem.Value.(*entry).value, true
}
return nil, false
}
func (c *LRUCache) Set(key string, val []byte) {
c.mu.Lock()
defer c.mu.Unlock()
if elem, ok := c.items[key]; ok {
c.evictList.MoveToFront(elem)
elem.Value.(*entry).value = val
return
}
elem := c.evictList.PushFront(&entry{key: key, value: val})
c.items[key] = elem
if c.evictList.Len() > c.capacity {
oldest := c.evictList.Back()
if oldest != nil {
c.evictList.Remove(oldest)
delete(c.items, oldest.Value.(*entry).key)
}
}
}