lru.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. package cache
  2. import (
  3. "container/list"
  4. sync "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 init 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. if v, ok := l.keyToElement.Load(key); ok {
  36. element := v.(*list.Element)
  37. l.doubleLinkedlist.MoveBefore(element, l.doubleLinkedlist.Front())
  38. return element.Value.(lruElement).value, true
  39. }
  40. return nil, false
  41. }
  42. func (l lru) GetKeyFromValue(value interface{}) (key interface{}, ok bool) {
  43. if k, ok := l.valueToElement.Load(value); ok {
  44. element := k.(*list.Element)
  45. l.doubleLinkedlist.MoveBefore(element, l.doubleLinkedlist.Front())
  46. return element.Value.(lruElement).key, true
  47. }
  48. return nil, false
  49. }
  50. func (l lru) PeekKeyFromValue(value interface{}) (key interface{}, ok bool) {
  51. if k, ok := l.valueToElement.Load(value); ok {
  52. element := k.(*list.Element)
  53. return element.Value.(lruElement).key, true
  54. }
  55. return nil, false
  56. }
  57. func (l lru) Put(key, value interface{}) {
  58. e := lruElement{key, value}
  59. if v, ok := l.keyToElement.Load(key); ok {
  60. element := v.(*list.Element)
  61. element.Value = e
  62. l.doubleLinkedlist.MoveBefore(element, l.doubleLinkedlist.Front())
  63. } else {
  64. l.mu.Lock()
  65. element := l.doubleLinkedlist.PushFront(e)
  66. l.keyToElement.Store(key, element)
  67. l.valueToElement.Store(value, element)
  68. if l.doubleLinkedlist.Len() > l.capacity {
  69. toBeRemove := l.doubleLinkedlist.Back()
  70. l.doubleLinkedlist.Remove(toBeRemove)
  71. l.keyToElement.Delete(toBeRemove.Value.(lruElement).key)
  72. l.valueToElement.Delete(toBeRemove.Value.(lruElement).value)
  73. }
  74. l.mu.Unlock()
  75. }
  76. }