github.com/searKing/golang/go@v1.2.117/exp/sync/lru.go (about) 1 // Copyright 2022 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package sync 6 7 import ( 8 "sync" 9 10 "github.com/searKing/golang/go/exp/container/lru" 11 ) 12 13 // EvictCallback is used to get a callback when a cache entry is evicted 14 // type EvictCallback[K comparable, V any] func(key K, value V) 15 type EvictCallback[K comparable, V any] lru.EvictCallback[K, V] 16 17 // LRU is like a Go map[K]V but implements a thread safe fixed size LRU cache. 18 // Loads, stores, and deletes run in amortized constant time. 19 // A LRU is safe for use by multiple goroutines simultaneously. 20 // A LRU must not be copied after first use. 21 type LRU[K comparable, V any] struct { 22 c *lru.LRU[K, V] 23 mu sync.Mutex 24 } 25 26 // NewLRU constructs an LRU of the given size 27 func NewLRU[K comparable, V any](size int) *LRU[K, V] { 28 return &LRU[K, V]{ 29 c: lru.New[K, V](size), 30 } 31 } 32 33 // SetEvictCallback sets a callback when a cache entry is evicted 34 func (c *LRU[K, V]) SetEvictCallback(onEvict EvictCallback[K, V]) *LRU[K, V] { 35 c.mu.Lock() 36 defer c.mu.Unlock() 37 c.c.SetEvictCallback(lru.EvictCallback[K, V](onEvict)) 38 return c 39 } 40 41 // SetEvictCallbackFunc sets a callback when a cache entry is evicted 42 // 43 // Deprecated, use SetEvictCallback instead. 44 func (c *LRU[K, V]) SetEvictCallbackFunc(onEvict func(key K, value V)) *LRU[K, V] { 45 c.mu.Lock() 46 defer c.mu.Unlock() 47 c.c.SetEvictCallback(onEvict) 48 return c 49 } 50 51 // Init initializes or clears LRU l. 52 func (c *LRU[K, V]) Init() *LRU[K, V] { 53 c.mu.Lock() 54 defer c.mu.Unlock() 55 c.c.Init() 56 return c 57 } 58 59 // Len returns the number of items in the cache. 60 func (c *LRU[K, V]) Len() int { 61 c.mu.Lock() 62 defer c.mu.Unlock() 63 return c.c.Len() 64 } 65 66 // Cap returns the capacity of the cache. 67 func (c *LRU[K, V]) Cap() int { 68 c.mu.Lock() 69 defer c.mu.Unlock() 70 return c.c.Cap() 71 } 72 73 // Resize changes the cache size. 74 func (c *LRU[K, V]) Resize(size int) (evicted int) { 75 c.mu.Lock() 76 defer c.mu.Unlock() 77 return c.c.Resize(size) 78 } 79 80 // Purge is used to completely clear the cache. 81 func (c *LRU[K, V]) Purge() { 82 c.mu.Lock() 83 defer c.mu.Unlock() 84 c.c.Purge() 85 } 86 87 // Load returns the value stored in the cache for a key, or zero if no 88 // value is present. 89 // The ok result indicates whether value was found in the cache. 90 func (c *LRU[K, V]) Load(key K) (value V, ok bool) { 91 c.mu.Lock() 92 defer c.mu.Unlock() 93 return c.c.Load(key) 94 } 95 96 // Get looks up a key's value from the cache, 97 // with updating the "recently used"-ness of the key. 98 func (c *LRU[K, V]) Get(key K) (value V, ok bool) { 99 c.mu.Lock() 100 defer c.mu.Unlock() 101 return c.c.Get(key) 102 } 103 104 // Peek returns the key value (or undefined if not found) without updating 105 // the "recently used"-ness of the key. 106 func (c *LRU[K, V]) Peek(key K) (value V, ok bool) { 107 return c.c.Peek(key) 108 } 109 110 // Contains checks if a key is in the cache, without updating the recent-ness 111 // or deleting it for being stale. 112 func (c *LRU[K, V]) Contains(key K) (ok bool) { 113 c.mu.Lock() 114 defer c.mu.Unlock() 115 return c.c.Contains(key) 116 } 117 118 // Store sets the value for a key. 119 func (c *LRU[K, V]) Store(key K, value V) { 120 c.mu.Lock() 121 defer c.mu.Unlock() 122 c.c.Store(key, value) 123 } 124 125 // Add adds a value to the cache. Returns true if an eviction occurred. 126 func (c *LRU[K, V]) Add(key K, value V) (evicted bool) { 127 c.mu.Lock() 128 defer c.mu.Unlock() 129 return c.c.Add(key, value) 130 } 131 132 // LoadOrStore returns the existing value for the key if present. 133 // Otherwise, it stores and returns the given value. 134 // The loaded result is true if the value was loaded, false if stored. 135 func (c *LRU[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) { 136 c.mu.Lock() 137 defer c.mu.Unlock() 138 return c.c.LoadOrStore(key, value) 139 } 140 141 // LoadAndDelete deletes the value for a key, returning the previous value if any. 142 // The loaded result reports whether the key was present. 143 func (c *LRU[K, V]) LoadAndDelete(key K) (value V, loaded bool) { 144 c.mu.Lock() 145 defer c.mu.Unlock() 146 return c.c.LoadAndDelete(key) 147 } 148 149 // Delete deletes the value for a key. 150 func (c *LRU[K, V]) Delete(key K) { 151 c.mu.Lock() 152 defer c.mu.Unlock() 153 c.c.Delete(key) 154 } 155 156 // Remove removes the provided key from the cache, returning if the 157 // key was contained. 158 func (c *LRU[K, V]) Remove(key K) (present bool) { 159 c.mu.Lock() 160 defer c.mu.Unlock() 161 return c.c.Remove(key) 162 } 163 164 // Swap swaps the value for a key and returns the previous value if any. 165 // The loaded result reports whether the key was present. 166 func (c *LRU[K, V]) Swap(key K, value V) (previous V, loaded bool) { 167 c.mu.Lock() 168 defer c.mu.Unlock() 169 return c.c.Swap(key, value) 170 } 171 172 // CompareAndSwap swaps the old and new values for key 173 // if the value stored in the map is equal to old. 174 // The old value must be of a comparable type. 175 func (c *LRU[K, V]) CompareAndSwap(key K, old, new V) (swapped bool) { 176 c.mu.Lock() 177 defer c.mu.Unlock() 178 return c.c.CompareAndSwap(key, old, new) 179 } 180 181 // CompareAndDelete deletes the entry for key if its value is equal to old. 182 // The old value must be of a comparable type. 183 // 184 // If there is no current value for key in the map, CompareAndDelete 185 // returns false (even if the old value is the nil interface value). 186 func (c *LRU[K, V]) CompareAndDelete(key K, old V) (deleted bool) { 187 c.mu.Lock() 188 defer c.mu.Unlock() 189 return c.c.CompareAndDelete(key, old) 190 } 191 192 // Keys returns a slice of the keys in the cache, from oldest to newest. 193 func (c *LRU[K, V]) Keys() []K { 194 c.mu.Lock() 195 defer c.mu.Unlock() 196 return c.c.Keys() 197 } 198 199 // Range calls f sequentially for each key and value present in the lru from oldest to newest. 200 // If f returns false, range stops the iteration. 201 // Without updating the "recently used"-ness of the key. 202 func (c *LRU[K, V]) Range(f func(key K, value V) bool) { 203 c.mu.Lock() 204 defer c.mu.Unlock() 205 c.c.Range(f) 206 } 207 208 // PeekOldest returns the value stored in the cache for the oldest entry, or zero if no 209 // value is present. 210 // The ok result indicates whether value was found in the cache. 211 // Without updating the "recently used"-ness of the key. 212 func (c *LRU[K, V]) PeekOldest() (key K, value V, ok bool) { 213 c.mu.Lock() 214 defer c.mu.Unlock() 215 return c.c.PeekOldest() 216 } 217 218 // PeekAndDeleteOldest deletes the value for a key, returning the previous value if any. 219 // The loaded result reports whether the key was present. 220 func (c *LRU[K, V]) PeekAndDeleteOldest() (key K, value V, loaded bool) { 221 c.mu.Lock() 222 defer c.mu.Unlock() 223 return c.c.PeekAndDeleteOldest() 224 } 225 226 // RemoveOldest removes the oldest item from the cache. 227 func (c *LRU[K, V]) RemoveOldest() (key K, value V, ok bool) { 228 c.mu.Lock() 229 defer c.mu.Unlock() 230 return c.c.RemoveOldest() 231 } 232 233 // GetOldest returns the oldest entry 234 func (c *LRU[K, V]) GetOldest() (key K, value V, ok bool) { 235 c.mu.Lock() 236 defer c.mu.Unlock() 237 return c.c.GetOldest() 238 }