1
0

lru.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package cache
  2. import (
  3. "container/list"
  4. "sync"
  5. )
  6. // Cache is an LRU cache. It is safe for concurrent access.
  7. type Cache struct {
  8. // MaxEntries is the maximum number of cache entries before
  9. // an item is evicted. Zero means no limit.
  10. MaxEntries int
  11. //Execute this callback function when an element is culled
  12. OnEvicted func(key Key, value interface{})
  13. ll *list.List //list
  14. cache sync.Map
  15. }
  16. // A Key may be any value that is comparable. See http://golang.org/ref/spec#Comparison_operators
  17. type Key interface{}
  18. type entry struct {
  19. key Key
  20. value interface{}
  21. }
  22. // New creates a new Cache.
  23. // If maxEntries is 0, the cache has no length limit.
  24. // that eviction is done by the caller.
  25. func New(maxEntries int) *Cache {
  26. return &Cache{
  27. MaxEntries: maxEntries,
  28. ll: list.New(),
  29. //cache: make(map[interface{}]*list.Element),
  30. }
  31. }
  32. // If the key value already exists, move the key to the front
  33. func (c *Cache) Add(key Key, value interface{}) {
  34. if ee, ok := c.cache.Load(key); ok {
  35. c.ll.MoveToFront(ee.(*list.Element)) // move to the front
  36. ee.(*list.Element).Value.(*entry).value = value
  37. return
  38. }
  39. ele := c.ll.PushFront(&entry{key, value})
  40. c.cache.Store(key, ele)
  41. if c.MaxEntries != 0 && c.ll.Len() > c.MaxEntries { // Remove the oldest element if the limit is exceeded
  42. c.RemoveOldest()
  43. }
  44. }
  45. // Get looks up a key's value from the cache.
  46. func (c *Cache) Get(key Key) (value interface{}, ok bool) {
  47. if ele, hit := c.cache.Load(key); hit {
  48. c.ll.MoveToFront(ele.(*list.Element))
  49. return ele.(*list.Element).Value.(*entry).value, true
  50. }
  51. return
  52. }
  53. // Remove removes the provided key from the cache.
  54. func (c *Cache) Remove(key Key) {
  55. if ele, hit := c.cache.Load(key); hit {
  56. c.removeElement(ele.(*list.Element))
  57. }
  58. }
  59. // RemoveOldest removes the oldest item from the cache.
  60. func (c *Cache) RemoveOldest() {
  61. ele := c.ll.Back()
  62. if ele != nil {
  63. c.removeElement(ele)
  64. }
  65. }
  66. func (c *Cache) removeElement(e *list.Element) {
  67. c.ll.Remove(e)
  68. kv := e.Value.(*entry)
  69. c.cache.Delete(kv.key)
  70. if c.OnEvicted != nil {
  71. c.OnEvicted(kv.key, kv.value)
  72. }
  73. }
  74. // Len returns the number of items in the cache.
  75. func (c *Cache) Len() int {
  76. return c.ll.Len()
  77. }
  78. // Clear purges all stored items from the cache.
  79. func (c *Cache) Clear() {
  80. if c.OnEvicted != nil {
  81. c.cache.Range(func(key, value interface{}) bool {
  82. kv := value.(*list.Element).Value.(*entry)
  83. c.OnEvicted(kv.key, kv.value)
  84. return true
  85. })
  86. }
  87. c.ll = nil
  88. }