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