lru.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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. defer c.lock.Unlock()
  37. return c.lru.Add(key, value)
  38. }
  39. // Get looks up a key's value from the cache.
  40. func (c *Cache) Get(key interface{}) (value interface{}, ok bool) {
  41. c.lock.Lock()
  42. defer c.lock.Unlock()
  43. return c.lru.Get(key)
  44. }
  45. // Contains checks if a key is in the cache, without updating the
  46. // recent-ness or deleting it for being stale.
  47. func (c *Cache) Contains(key interface{}) bool {
  48. c.lock.RLock()
  49. defer c.lock.RUnlock()
  50. return c.lru.Contains(key)
  51. }
  52. // Peek returns the key value (or undefined if not found) without updating
  53. // the "recently used"-ness of the key.
  54. func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) {
  55. c.lock.RLock()
  56. defer c.lock.RUnlock()
  57. return c.lru.Peek(key)
  58. }
  59. // ContainsOrAdd checks if a key is in the cache without updating the
  60. // recent-ness or deleting it for being stale, and if not, adds the value.
  61. // Returns whether found and whether an eviction occurred.
  62. func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
  63. c.lock.Lock()
  64. defer c.lock.Unlock()
  65. if c.lru.Contains(key) {
  66. return true, false
  67. }
  68. evicted = c.lru.Add(key, value)
  69. return false, evicted
  70. }
  71. // Remove removes the provided key from the cache.
  72. func (c *Cache) Remove(key interface{}) {
  73. c.lock.Lock()
  74. c.lru.Remove(key)
  75. c.lock.Unlock()
  76. }
  77. // RemoveOldest removes the oldest item from the cache.
  78. func (c *Cache) RemoveOldest() {
  79. c.lock.Lock()
  80. c.lru.RemoveOldest()
  81. c.lock.Unlock()
  82. }
  83. // Keys returns a slice of the keys in the cache, from oldest to newest.
  84. func (c *Cache) Keys() []interface{} {
  85. c.lock.RLock()
  86. defer c.lock.RUnlock()
  87. return c.lru.Keys()
  88. }
  89. // Len returns the number of items in the cache.
  90. func (c *Cache) Len() int {
  91. c.lock.RLock()
  92. defer c.lock.RUnlock()
  93. return c.lru.Len()
  94. }