lru.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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. PeekKeyFromValue(value interface{}) (key interface{}, ok bool) // Peek means check but NOT bring to top
  11. Put(key, value interface{})
  12. }
  13. type lru struct {
  14. capacity int
  15. doubleLinkedlist *list.List
  16. keyToElement *sync.Map
  17. valueToElement *sync.Map
  18. mu *sync.Mutex
  19. }
  20. type lruElement struct {
  21. key interface{}
  22. value interface{}
  23. }
  24. // NewLru initializes a lru cache
  25. func NewLru(cap int) Lru {
  26. return &lru{
  27. capacity: cap,
  28. doubleLinkedlist: list.New(),
  29. keyToElement: new(sync.Map),
  30. valueToElement: new(sync.Map),
  31. mu: new(sync.Mutex),
  32. }
  33. }
  34. func (l *lru) Get(key interface{}) (value interface{}, ok bool) {
  35. l.mu.Lock()
  36. defer l.mu.Unlock()
  37. if v, ok := l.keyToElement.Load(key); ok {
  38. element := v.(*list.Element)
  39. l.doubleLinkedlist.MoveToFront(element)
  40. return element.Value.(*lruElement).value, true
  41. }
  42. return nil, false
  43. }
  44. func (l *lru) GetKeyFromValue(value interface{}) (key interface{}, ok bool) {
  45. l.mu.Lock()
  46. defer l.mu.Unlock()
  47. if k, ok := l.valueToElement.Load(value); ok {
  48. element := k.(*list.Element)
  49. l.doubleLinkedlist.MoveToFront(element)
  50. return element.Value.(*lruElement).key, true
  51. }
  52. return nil, false
  53. }
  54. func (l *lru) PeekKeyFromValue(value interface{}) (key interface{}, ok bool) {
  55. if k, ok := l.valueToElement.Load(value); ok {
  56. element := k.(*list.Element)
  57. return element.Value.(*lruElement).key, true
  58. }
  59. return nil, false
  60. }
  61. func (l *lru) Put(key, value interface{}) {
  62. l.mu.Lock()
  63. e := &lruElement{key, value}
  64. if v, ok := l.keyToElement.Load(key); ok {
  65. element := v.(*list.Element)
  66. element.Value = e
  67. l.doubleLinkedlist.MoveToFront(element)
  68. } else {
  69. element := l.doubleLinkedlist.PushFront(e)
  70. l.keyToElement.Store(key, element)
  71. l.valueToElement.Store(value, element)
  72. if l.doubleLinkedlist.Len() > l.capacity {
  73. toBeRemove := l.doubleLinkedlist.Back()
  74. l.doubleLinkedlist.Remove(toBeRemove)
  75. l.keyToElement.Delete(toBeRemove.Value.(*lruElement).key)
  76. l.valueToElement.Delete(toBeRemove.Value.(*lruElement).value)
  77. }
  78. }
  79. l.mu.Unlock()
  80. }