Refinement: LRU (#1142) (#775)

Co-authored-by: Loyalsoldier <10487845+Loyalsoldier@users.noreply.github.com>
This commit is contained in:
yuhan6665 2021-10-19 12:53:29 -04:00 committed by GitHub
parent 500c6de359
commit d77be80b40
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

38
common/cache/lru.go vendored
View file

@ -2,7 +2,7 @@ package cache
import ( import (
"container/list" "container/list"
sync "sync" "sync"
) )
// Lru simple, fast lru cache implementation // Lru simple, fast lru cache implementation
@ -28,7 +28,7 @@ type lruElement struct {
// NewLru init a lru cache // NewLru init a lru cache
func NewLru(cap int) Lru { func NewLru(cap int) Lru {
return lru{ return &lru{
capacity: cap, capacity: cap,
doubleLinkedlist: list.New(), doubleLinkedlist: list.New(),
keyToElement: new(sync.Map), keyToElement: new(sync.Map),
@ -37,49 +37,53 @@ func NewLru(cap int) Lru {
} }
} }
func (l lru) Get(key interface{}) (value interface{}, ok bool) { 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 { if v, ok := l.keyToElement.Load(key); ok {
element := v.(*list.Element) element := v.(*list.Element)
l.doubleLinkedlist.MoveBefore(element, l.doubleLinkedlist.Front()) l.doubleLinkedlist.MoveToFront(element)
return element.Value.(lruElement).value, true return element.Value.(*lruElement).value, true
} }
return nil, false return nil, false
} }
func (l lru) GetKeyFromValue(value interface{}) (key interface{}, ok bool) { 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 { if k, ok := l.valueToElement.Load(value); ok {
element := k.(*list.Element) element := k.(*list.Element)
l.doubleLinkedlist.MoveBefore(element, l.doubleLinkedlist.Front()) l.doubleLinkedlist.MoveToFront(element)
return element.Value.(lruElement).key, true return element.Value.(*lruElement).key, true
} }
return nil, false return nil, false
} }
func (l lru) PeekKeyFromValue(value interface{}) (key interface{}, ok bool) { func (l *lru) PeekKeyFromValue(value interface{}) (key interface{}, ok bool) {
if k, ok := l.valueToElement.Load(value); ok { if k, ok := l.valueToElement.Load(value); ok {
element := k.(*list.Element) element := k.(*list.Element)
return element.Value.(lruElement).key, true return element.Value.(*lruElement).key, true
} }
return nil, false return nil, false
} }
func (l lru) Put(key, value interface{}) { func (l *lru) Put(key, value interface{}) {
e := lruElement{key, value} l.mu.Lock()
e := &lruElement{key, value}
if v, ok := l.keyToElement.Load(key); ok { if v, ok := l.keyToElement.Load(key); ok {
element := v.(*list.Element) element := v.(*list.Element)
element.Value = e element.Value = e
l.doubleLinkedlist.MoveBefore(element, l.doubleLinkedlist.Front()) l.doubleLinkedlist.MoveToFront(element)
} else { } else {
l.mu.Lock()
element := l.doubleLinkedlist.PushFront(e) element := l.doubleLinkedlist.PushFront(e)
l.keyToElement.Store(key, element) l.keyToElement.Store(key, element)
l.valueToElement.Store(value, element) l.valueToElement.Store(value, element)
if l.doubleLinkedlist.Len() > l.capacity { if l.doubleLinkedlist.Len() > l.capacity {
toBeRemove := l.doubleLinkedlist.Back() toBeRemove := l.doubleLinkedlist.Back()
l.doubleLinkedlist.Remove(toBeRemove) l.doubleLinkedlist.Remove(toBeRemove)
l.keyToElement.Delete(toBeRemove.Value.(lruElement).key) l.keyToElement.Delete(toBeRemove.Value.(*lruElement).key)
l.valueToElement.Delete(toBeRemove.Value.(lruElement).value) l.valueToElement.Delete(toBeRemove.Value.(*lruElement).value)
} }
l.mu.Unlock()
} }
l.mu.Unlock()
} }