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