You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

117 lines
2.7 KiB

  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. // Remove removes the provided key from the cache.
  76. func (c *Cache) Remove(key interface{}) {
  77. c.lock.Lock()
  78. c.lru.Remove(key)
  79. c.lock.Unlock()
  80. }
  81. // RemoveOldest removes the oldest item from the cache.
  82. func (c *Cache) RemoveOldest() {
  83. c.lock.Lock()
  84. c.lru.RemoveOldest()
  85. c.lock.Unlock()
  86. }
  87. // Keys returns a slice of the keys in the cache, from oldest to newest.
  88. func (c *Cache) Keys() []interface{} {
  89. c.lock.RLock()
  90. keys := c.lru.Keys()
  91. c.lock.RUnlock()
  92. return keys
  93. }
  94. // Len returns the number of items in the cache.
  95. func (c *Cache) Len() int {
  96. c.lock.RLock()
  97. length := c.lru.Len()
  98. c.lock.RUnlock()
  99. return length
  100. }