lru.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // This package provides a simple LRU cache. It is based on the
  2. // LRU implementation in groupcache:
  3. // https://github.com/golang/groupcache/tree/master/lru
  4. package lru
  5. import (
  6. "sync"
  7. "github.com/hashicorp/golang-lru/simplelru"
  8. )
  9. // Cache is a thread-safe fixed size LRU cache.
  10. type Cache struct {
  11. lru *simplelru.LRU
  12. lock sync.RWMutex
  13. }
  14. // New creates an LRU of the given size
  15. func New(size int) (*Cache, error) {
  16. return NewWithEvict(size, nil)
  17. }
  18. // NewWithEvict constructs a fixed size cache with the given eviction
  19. // callback.
  20. func NewWithEvict(size int, onEvicted func(key interface{}, value interface{})) (*Cache, error) {
  21. lru, err := simplelru.NewLRU(size, simplelru.EvictCallback(onEvicted))
  22. if err != nil {
  23. return nil, err
  24. }
  25. c := &Cache{
  26. lru: lru,
  27. }
  28. return c, nil
  29. }
  30. // Purge is used to completely clear the cache
  31. func (c *Cache) Purge() {
  32. c.lock.Lock()
  33. c.lru.Purge()
  34. c.lock.Unlock()
  35. }
  36. // Add adds a value to the cache. Returns true if an eviction occurred.
  37. func (c *Cache) Add(key, value interface{}) bool {
  38. c.lock.Lock()
  39. defer c.lock.Unlock()
  40. return c.lru.Add(key, value)
  41. }
  42. // Get looks up a key's value from the cache.
  43. func (c *Cache) Get(key interface{}) (interface{}, bool) {
  44. c.lock.Lock()
  45. defer c.lock.Unlock()
  46. return c.lru.Get(key)
  47. }
  48. // Check if a key is in the cache, without updating the recent-ness
  49. // or deleting it for being stale.
  50. func (c *Cache) Contains(key interface{}) bool {
  51. c.lock.RLock()
  52. defer c.lock.RUnlock()
  53. return c.lru.Contains(key)
  54. }
  55. // 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{}) (interface{}, bool) {
  58. c.lock.RLock()
  59. defer c.lock.RUnlock()
  60. return c.lru.Peek(key)
  61. }
  62. // ContainsOrAdd checks if a key is in the cache without updating the
  63. // recent-ness or deleting it for being stale, and if not, adds the value.
  64. // Returns whether found and whether an eviction occurred.
  65. func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evict bool) {
  66. c.lock.Lock()
  67. defer c.lock.Unlock()
  68. if c.lru.Contains(key) {
  69. return true, false
  70. } else {
  71. evict := c.lru.Add(key, value)
  72. return false, evict
  73. }
  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. defer c.lock.RUnlock()
  91. return c.lru.Keys()
  92. }
  93. // Len returns the number of items in the cache.
  94. func (c *Cache) Len() int {
  95. c.lock.RLock()
  96. defer c.lock.RUnlock()
  97. return c.lru.Len()
  98. }