lru.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. package lru
  2. import (
  3. "sync"
  4. "github.com/hashicorp/golang-lru/simplelru"
  5. )
  6. // Cache is a thread-safe fixed size LRU cache.
  7. type Cache struct {
  8. lru simplelru.LRUCache
  9. lock sync.RWMutex
  10. }
  11. // New creates an LRU of the given size.
  12. func New(size int) (*Cache, error) {
  13. return NewWithEvict(size, nil)
  14. }
  15. // NewWithEvict constructs a fixed size cache with the given eviction
  16. // callback.
  17. func NewWithEvict(size int, onEvicted func(key interface{}, value interface{})) (*Cache, error) {
  18. lru, err := simplelru.NewLRU(size, simplelru.EvictCallback(onEvicted))
  19. if err != nil {
  20. return nil, err
  21. }
  22. c := &Cache{
  23. lru: lru,
  24. }
  25. return c, nil
  26. }
  27. // Purge is used to completely clear the cache.
  28. func (c *Cache) Purge() {
  29. c.lock.Lock()
  30. c.lru.Purge()
  31. c.lock.Unlock()
  32. }
  33. // Add adds a value to the cache. Returns true if an eviction occurred.
  34. func (c *Cache) Add(key, value interface{}) (evicted bool) {
  35. c.lock.Lock()
  36. evicted = c.lru.Add(key, value)
  37. c.lock.Unlock()
  38. return evicted
  39. }
  40. // Get looks up a key's value from the cache.
  41. func (c *Cache) Get(key interface{}) (value interface{}, ok bool) {
  42. c.lock.Lock()
  43. value, ok = c.lru.Get(key)
  44. c.lock.Unlock()
  45. return value, ok
  46. }
  47. // Contains checks if a key is in the cache, without updating the
  48. // recent-ness or deleting it for being stale.
  49. func (c *Cache) Contains(key interface{}) bool {
  50. c.lock.RLock()
  51. containKey := c.lru.Contains(key)
  52. c.lock.RUnlock()
  53. return containKey
  54. }
  55. // Peek returns the key value (or undefined if not found) without updating
  56. // the "recently used"-ness of the key.
  57. func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) {
  58. c.lock.RLock()
  59. value, ok = c.lru.Peek(key)
  60. c.lock.RUnlock()
  61. return value, ok
  62. }
  63. // ContainsOrAdd checks if a key is in the cache without updating the
  64. // recent-ness or deleting it for being stale, and if not, adds the value.
  65. // Returns whether found and whether an eviction occurred.
  66. func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
  67. c.lock.Lock()
  68. defer c.lock.Unlock()
  69. if c.lru.Contains(key) {
  70. return true, false
  71. }
  72. evicted = c.lru.Add(key, value)
  73. return false, evicted
  74. }
  75. // PeekOrAdd checks if a key is in the cache without updating the
  76. // recent-ness or deleting it for being stale, and if not, adds the value.
  77. // Returns whether found and whether an eviction occurred.
  78. func (c *Cache) PeekOrAdd(key, value interface{}) (previous interface{}, ok, evicted bool) {
  79. c.lock.Lock()
  80. defer c.lock.Unlock()
  81. previous, ok = c.lru.Peek(key)
  82. if ok {
  83. return previous, true, false
  84. }
  85. evicted = c.lru.Add(key, value)
  86. return nil, false, evicted
  87. }
  88. // Remove removes the provided key from the cache.
  89. func (c *Cache) Remove(key interface{}) (present bool) {
  90. c.lock.Lock()
  91. present = c.lru.Remove(key)
  92. c.lock.Unlock()
  93. return
  94. }
  95. // Resize changes the cache size.
  96. func (c *Cache) Resize(size int) (evicted int) {
  97. c.lock.Lock()
  98. evicted = c.lru.Resize(size)
  99. c.lock.Unlock()
  100. return evicted
  101. }
  102. // RemoveOldest removes the oldest item from the cache.
  103. func (c *Cache) RemoveOldest() (key interface{}, value interface{}, ok bool) {
  104. c.lock.Lock()
  105. key, value, ok = c.lru.RemoveOldest()
  106. c.lock.Unlock()
  107. return
  108. }
  109. // GetOldest returns the oldest entry
  110. func (c *Cache) GetOldest() (key interface{}, value interface{}, ok bool) {
  111. c.lock.Lock()
  112. key, value, ok = c.lru.GetOldest()
  113. c.lock.Unlock()
  114. return
  115. }
  116. // Keys returns a slice of the keys in the cache, from oldest to newest.
  117. func (c *Cache) Keys() []interface{} {
  118. c.lock.RLock()
  119. keys := c.lru.Keys()
  120. c.lock.RUnlock()
  121. return keys
  122. }
  123. // Len returns the number of items in the cache.
  124. func (c *Cache) Len() int {
  125. c.lock.RLock()
  126. length := c.lru.Len()
  127. c.lock.RUnlock()
  128. return length
  129. }