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  }