lru.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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. 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. if v, ok := l.keyToElement.Load(key); ok {
  35. element := v.(*list.Element)
  36. l.doubleLinkedlist.MoveBefore(element, l.doubleLinkedlist.Front())
  37. return element.Value.(lruElement).value, true
  38. }
  39. return nil, false
  40. }
  41. func (l lru) GetKeyFromValue(value interface{}) (key interface{}, ok bool) {
  42. if k, ok := l.valueToElement.Load(value); ok {
  43. element := k.(*list.Element)
  44. l.doubleLinkedlist.MoveBefore(element, l.doubleLinkedlist.Front())
  45. return element.Value.(lruElement).key, true
  46. }
  47. return nil, false
  48. }
  49. func (l lru) Put(key, value interface{}) {
  50. e := lruElement{key, value}
  51. if v, ok := l.keyToElement.Load(key); ok {
  52. element := v.(*list.Element)
  53. element.Value = e
  54. l.doubleLinkedlist.MoveBefore(element, l.doubleLinkedlist.Front())
  55. } else {
  56. l.mu.Lock()
  57. element := l.doubleLinkedlist.PushFront(e)
  58. l.keyToElement.Store(key, element)
  59. l.valueToElement.Store(value, element)
  60. if l.doubleLinkedlist.Len() > l.capacity {
  61. toBeRemove := l.doubleLinkedlist.Back()
  62. l.doubleLinkedlist.Remove(toBeRemove)
  63. l.keyToElement.Delete(toBeRemove.Value.(lruElement).key)
  64. l.valueToElement.Delete(toBeRemove.Value.(lruElement).value)
  65. }
  66. l.mu.Unlock()
  67. }
  68. }