lru.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package cache
  2. import (
  3. "container/list"
  4. "sync"
  5. )
  6. // Lru simple, fast lru cache implementation
  7. type Lru interface {
  8. Get(key interface{}) (value interface{}, ok bool)
  9. GetKeyFromValue(value interface{}) (key interface{}, ok bool)
  10. Put(key, value interface{})
  11. }
  12. type lru struct {
  13. capacity int
  14. doubleLinkedlist *list.List
  15. keyToElement *sync.Map
  16. valueToElement *sync.Map
  17. mu *sync.Mutex
  18. }
  19. type lruElement struct {
  20. key interface{}
  21. value interface{}
  22. }
  23. // NewLru init a lru cache
  24. func NewLru(cap int) Lru {
  25. return &lru{
  26. capacity: cap,
  27. doubleLinkedlist: list.New(),
  28. keyToElement: new(sync.Map),
  29. valueToElement: new(sync.Map),
  30. mu: new(sync.Mutex),
  31. }
  32. }
  33. func (l *lru) Get(key interface{}) (value interface{}, ok bool) {
  34. l.mu.Lock()
  35. defer l.mu.Unlock()
  36. if v, ok := l.keyToElement.Load(key); ok {
  37. element := v.(*list.Element)
  38. l.doubleLinkedlist.MoveToFront(element)
  39. return element.Value.(*lruElement).value, true
  40. }
  41. return nil, false
  42. }
  43. func (l *lru) GetKeyFromValue(value interface{}) (key interface{}, ok bool) {
  44. l.mu.Lock()
  45. defer l.mu.Unlock()
  46. if k, ok := l.valueToElement.Load(value); ok {
  47. element := k.(*list.Element)
  48. l.doubleLinkedlist.MoveToFront(element)
  49. return element.Value.(*lruElement).key, true
  50. }
  51. return nil, false
  52. }
  53. func (l *lru) Put(key, value interface{}) {
  54. l.mu.Lock()
  55. e := &lruElement{key, value}
  56. if v, ok := l.keyToElement.Load(key); ok {
  57. element := v.(*list.Element)
  58. element.Value = e
  59. l.doubleLinkedlist.MoveToFront(element)
  60. } else {
  61. element := l.doubleLinkedlist.PushFront(e)
  62. l.keyToElement.Store(key, element)
  63. l.valueToElement.Store(value, element)
  64. if l.doubleLinkedlist.Len() > l.capacity {
  65. toBeRemove := l.doubleLinkedlist.Back()
  66. l.doubleLinkedlist.Remove(toBeRemove)
  67. l.keyToElement.Delete(toBeRemove.Value.(*lruElement).key)
  68. l.valueToElement.Delete(toBeRemove.Value.(*lruElement).value)
  69. }
  70. }
  71. l.mu.Unlock()
  72. }