| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- package cache
- import (
- "container/list"
- "sync"
- )
- // Lru simple, fast lru cache implementation
- type Lru interface {
- Get(key interface{}) (value interface{}, ok bool)
- GetKeyFromValue(value interface{}) (key interface{}, ok bool)
- PeekKeyFromValue(value interface{}) (key interface{}, ok bool) // Peek means check but NOT bring to top
- Put(key, value interface{})
- }
- type lru struct {
- capacity int
- doubleLinkedlist *list.List
- keyToElement *sync.Map
- valueToElement *sync.Map
- mu *sync.Mutex
- }
- type lruElement struct {
- key interface{}
- value interface{}
- }
- // NewLru initializes a lru cache
- func NewLru(cap int) Lru {
- return &lru{
- capacity: cap,
- doubleLinkedlist: list.New(),
- keyToElement: new(sync.Map),
- valueToElement: new(sync.Map),
- mu: new(sync.Mutex),
- }
- }
- func (l *lru) Get(key interface{}) (value interface{}, ok bool) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if v, ok := l.keyToElement.Load(key); ok {
- element := v.(*list.Element)
- l.doubleLinkedlist.MoveToFront(element)
- return element.Value.(*lruElement).value, true
- }
- return nil, false
- }
- func (l *lru) GetKeyFromValue(value interface{}) (key interface{}, ok bool) {
- l.mu.Lock()
- defer l.mu.Unlock()
- if k, ok := l.valueToElement.Load(value); ok {
- element := k.(*list.Element)
- l.doubleLinkedlist.MoveToFront(element)
- return element.Value.(*lruElement).key, true
- }
- return nil, false
- }
- func (l *lru) PeekKeyFromValue(value interface{}) (key interface{}, ok bool) {
- if k, ok := l.valueToElement.Load(value); ok {
- element := k.(*list.Element)
- return element.Value.(*lruElement).key, true
- }
- return nil, false
- }
- func (l *lru) Put(key, value interface{}) {
- l.mu.Lock()
- e := &lruElement{key, value}
- if v, ok := l.keyToElement.Load(key); ok {
- element := v.(*list.Element)
- element.Value = e
- l.doubleLinkedlist.MoveToFront(element)
- } else {
- element := l.doubleLinkedlist.PushFront(e)
- l.keyToElement.Store(key, element)
- l.valueToElement.Store(value, element)
- if l.doubleLinkedlist.Len() > l.capacity {
- toBeRemove := l.doubleLinkedlist.Back()
- l.doubleLinkedlist.Remove(toBeRemove)
- l.keyToElement.Delete(toBeRemove.Value.(*lruElement).key)
- l.valueToElement.Delete(toBeRemove.Value.(*lruElement).value)
- }
- }
- l.mu.Unlock()
- }
|