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  }