github.com/fufuok/freelru@v0.13.3/syncedlru.go (about) 1 package freelru 2 3 import ( 4 "sync" 5 "time" 6 ) 7 8 type SyncedLRU[K comparable, V any] struct { 9 mu sync.RWMutex 10 lru *LRU[K, V] 11 } 12 13 var _ Cache[int, int] = (*SyncedLRU[int, int])(nil) 14 15 // SetLifetime sets the default lifetime of LRU elements. 16 // Lifetime 0 means "forever". 17 func (lru *SyncedLRU[K, V]) SetLifetime(lifetime time.Duration) { 18 lru.mu.Lock() 19 lru.lru.SetLifetime(lifetime) 20 lru.mu.Unlock() 21 } 22 23 // SetOnEvict sets the OnEvict callback function. 24 // The onEvict function is called for each evicted lru entry. 25 func (lru *SyncedLRU[K, V]) SetOnEvict(onEvict OnEvictCallback[K, V]) { 26 lru.mu.Lock() 27 lru.lru.SetOnEvict(onEvict) 28 lru.mu.Unlock() 29 } 30 31 // NewSynced creates a new thread-safe LRU hashmap with the given capacity. 32 func NewSynced[K comparable, V any](capacity uint32, hash HashKeyCallback[K]) (*SyncedLRU[K, V], error) { 33 return NewSyncedWithSize[K, V](capacity, capacity, hash) 34 } 35 36 func NewSyncedWithSize[K comparable, V any](capacity, size uint32, hash HashKeyCallback[K]) (*SyncedLRU[K, V], error) { 37 lru, err := NewWithSize[K, V](capacity, size, hash) 38 if err != nil { 39 return nil, err 40 } 41 return &SyncedLRU[K, V]{lru: lru}, nil 42 } 43 44 // Len returns the number of elements stored in the cache. 45 func (lru *SyncedLRU[K, V]) Len() (length int) { 46 lru.mu.RLock() 47 length = lru.lru.Len() 48 lru.mu.RUnlock() 49 50 return 51 } 52 53 // AddWithLifetime adds a key:value to the cache with a lifetime. 54 // Returns true, true if key was updated and eviction occurred. 55 func (lru *SyncedLRU[K, V]) AddWithLifetime(key K, value V, lifetime time.Duration) (evicted bool) { 56 hash := lru.lru.hash(key) 57 58 lru.mu.Lock() 59 evicted = lru.lru.addWithLifetime(hash, key, value, lifetime) 60 lru.mu.Unlock() 61 62 return 63 } 64 65 // Add adds a key:value to the cache. 66 // Returns true, true if key was updated and eviction occurred. 67 func (lru *SyncedLRU[K, V]) Add(key K, value V) (evicted bool) { 68 hash := lru.lru.hash(key) 69 70 lru.mu.Lock() 71 evicted = lru.lru.add(hash, key, value) 72 lru.mu.Unlock() 73 74 return 75 } 76 77 // Get looks up a key's value from the cache, setting it as the most 78 // recently used item. 79 func (lru *SyncedLRU[K, V]) Get(key K) (value V, ok bool) { 80 hash := lru.lru.hash(key) 81 82 lru.mu.Lock() 83 value, ok = lru.lru.get(hash, key) 84 lru.mu.Unlock() 85 86 return 87 } 88 89 // Peek looks up a key's value from the cache, without changing its recent-ness. 90 func (lru *SyncedLRU[K, V]) Peek(key K) (value V, ok bool) { 91 hash := lru.lru.hash(key) 92 93 lru.mu.RLock() 94 value, ok = lru.lru.peek(hash, key) 95 lru.mu.RUnlock() 96 97 return 98 } 99 100 // Contains checks for the existence of a key, without changing its recent-ness. 101 func (lru *SyncedLRU[K, V]) Contains(key K) (ok bool) { 102 hash := lru.lru.hash(key) 103 104 lru.mu.RLock() 105 ok = lru.lru.contains(hash, key) 106 lru.mu.RUnlock() 107 108 return 109 } 110 111 // Remove removes the key from the cache. 112 // The return value indicates whether the key existed or not. 113 func (lru *SyncedLRU[K, V]) Remove(key K) (removed bool) { 114 hash := lru.lru.hash(key) 115 116 lru.mu.Lock() 117 removed = lru.lru.remove(hash, key) 118 lru.mu.Unlock() 119 120 return 121 } 122 123 // Keys returns a slice of the keys in the cache, from oldest to newest. 124 func (lru *SyncedLRU[K, V]) Keys() (keys []K) { 125 lru.mu.RLock() 126 keys = lru.lru.Keys() 127 lru.mu.RUnlock() 128 129 return 130 } 131 132 // Purge purges all data (key and value) from the LRU. 133 func (lru *SyncedLRU[K, V]) Purge() { 134 lru.mu.Lock() 135 lru.lru.Purge() 136 lru.mu.Unlock() 137 } 138 139 // Metrics returns the metrics of the cache. 140 func (lru *SyncedLRU[K, V]) Metrics() Metrics { 141 lru.mu.Lock() 142 metrics := lru.lru.Metrics() 143 lru.mu.Unlock() 144 return metrics 145 } 146 147 // ResetMetrics resets the metrics of the cache and returns the previous state. 148 func (lru *SyncedLRU[K, V]) ResetMetrics() Metrics { 149 lru.mu.Lock() 150 metrics := lru.lru.ResetMetrics() 151 lru.mu.Unlock() 152 return metrics 153 } 154 155 // just used for debugging 156 func (lru *SyncedLRU[K, V]) dump() { 157 lru.mu.RLock() 158 lru.lru.dump() 159 lru.mu.RUnlock() 160 } 161 162 func (lru *SyncedLRU[K, V]) PrintStats() { 163 lru.mu.RLock() 164 lru.lru.PrintStats() 165 lru.mu.RUnlock() 166 }