Advertisement
mahldcat

LRUCache.cs

Dec 16th, 2024 (edited)
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.36 KB | None | 0 0
  1. namespace Cache;
  2.  
  3. public class LRUCache<K,V> where K: notnull
  4. {
  5.     private record struct CacheItem<K, V>(K Key, V Value)
  6.     {
  7.         public K Key { get;} = Key;
  8.     }
  9.    
  10.     private SemaphoreSlim _lockSync = new SemaphoreSlim(1,1);
  11.     private int _capacity;
  12.     private readonly Dictionary<K, CacheItem<K,V>> _cache;
  13.     private readonly LinkedList<CacheItem<K,V>> _accessOrder;
  14.  
  15.     public LRUCache(int capacity)
  16.     {
  17.         if (capacity <= 0)
  18.         {
  19.             throw new ArgumentOutOfRangeException(nameof(capacity), capacity, "capacity must be >0");
  20.         }
  21.         _capacity = capacity;
  22.         _cache = new Dictionary<K, CacheItem<K,V>>(capacity);
  23.         _accessOrder = new LinkedList<CacheItem<K, V>>();
  24.     }
  25.  
  26.     public int Capacity
  27.     {
  28.         get
  29.         {
  30.             return _capacity;
  31.         }
  32.         set
  33.         {
  34.             UpdateCapacity(value);
  35.         }
  36.     }
  37.  
  38.     private void UpdateCapacity(int newCapacity)
  39.     {
  40.         if (newCapacity <= 0)
  41.         {
  42.             throw new ArgumentOutOfRangeException(nameof(newCapacity), newCapacity, "new capacity must be >0");
  43.         }
  44.        
  45.         _lockSync.Wait();
  46.         try
  47.         {
  48.  
  49.  
  50.             while (_accessOrder.Count > newCapacity)
  51.             {
  52.                 var lastNode = _accessOrder.Last;
  53.                 _cache.Remove(lastNode.Value.Key);
  54.                 _accessOrder.RemoveLast();
  55.             }
  56.  
  57.             _cache.EnsureCapacity(newCapacity);
  58.             _capacity = newCapacity;
  59.         }
  60.         finally
  61.         {
  62.             _lockSync.Release();
  63.         }
  64.     }
  65.    
  66.     public V this[K key]
  67.     {
  68.         get
  69.         {
  70.             return this.Get(key);
  71.         }
  72.         set
  73.         {
  74.             this.AddOrUpdate(key,value);
  75.         }
  76.     }
  77.    
  78.     public V Get(K key)
  79.     {
  80.         _lockSync.Wait();
  81.         try
  82.         {
  83.             if (_cache.TryGetValue(key, out var node))
  84.             {
  85.                 _accessOrder.Remove(node);
  86.                 _accessOrder.AddFirst(node);
  87.                 return node.Value;
  88.             }
  89.             throw new KeyNotFoundException("key is not found");
  90.         }
  91.         finally
  92.         {
  93.             _lockSync.Release();
  94.         }
  95.  
  96.     }
  97.  
  98.     public void AddOrUpdate(K key, V value)
  99.     {
  100.         _lockSync.Wait();
  101.         try
  102.         {
  103.             if (_cache.TryGetValue(key, out var node))
  104.             {
  105.                 _accessOrder.Remove(node);
  106.                 _accessOrder.AddFirst(node);
  107.                 node.Value = value;
  108.                 _cache[key] = node;
  109.             }
  110.             else
  111.             {
  112.                 CacheItem<K, V> newItem = new CacheItem<K, V>(key, value);
  113.                 if (_cache.Count == _capacity)
  114.                 {
  115.                     var lastItem = _accessOrder.Last;
  116.                     _cache.Remove(lastItem.Value.Key);
  117.                     _accessOrder.RemoveLast();
  118.                 }
  119.  
  120.                 _accessOrder.AddFirst(newItem);
  121.                 _cache.Add(key, newItem);
  122.             }
  123.         }
  124.         finally
  125.         {
  126.             _lockSync.Release();
  127.         }
  128.     }
  129.    
  130.     public void Add(K key, V value)
  131.     {
  132.         _lockSync.Wait();
  133.         try
  134.         {
  135.             if (!_cache.ContainsKey(key))
  136.             {
  137.                 CacheItem<K, V> newItem = new CacheItem<K, V>(key, value);
  138.  
  139.                 if (_cache.Count == _capacity)
  140.                 {
  141.                     var lastItem = _accessOrder.Last;
  142.                     _cache.Remove(lastItem.Value.Key);
  143.                     _accessOrder.RemoveLast();
  144.                 }
  145.  
  146.                 _accessOrder.AddFirst(newItem);
  147.                 _cache.Add(key, newItem);
  148.             }
  149.             else
  150.             {
  151.                 throw new Exception("key already exists");
  152.             }
  153.         }
  154.         finally
  155.         {
  156.             _lockSync.Release();
  157.         }        
  158.     }
  159.  
  160.     public V Remove(K key)
  161.     {
  162.         _lockSync.Wait();
  163.         try
  164.         {
  165.             if (_cache.TryGetValue(key, out var cacheItem))
  166.             {
  167.                 _cache.Remove(key);
  168.                 _accessOrder.Remove(cacheItem);
  169.                 return cacheItem.Value;
  170.             }
  171.             throw new KeyNotFoundException("Key does not exist");
  172.         }
  173.         finally
  174.         {
  175.             _lockSync.Release();
  176.         }
  177.     }
  178. }
  179.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement