public async void AddOrUpdate(string key, object value) { SemaphoreSlim item_lock = _locks.GetOrAdd(key, k => new SemaphoreSlim(1, 1)); await item_lock.WaitAsync(); try { var cacheItemNode = new CacheItemNode(key, value); if (_memoryCache.Contains(key)) { CacheItemNode source = (CacheItemNode)_memoryCache.Get(key); _lRUQueue.Remove(source); _lRUQueue.MoveToFront(cacheItemNode); _memoryCache.Remove(key); _memoryCache.Set(key, cacheItemNode, _policy); OnUpdate(source, cacheItemNode); } else { OnAdd(key); _memoryCache.Set(key, cacheItemNode, _policy); _lRUQueue.MoveToFront(cacheItemNode); // For DEBUG purpose Console.WriteLine($"LRU queue state = {_lRUQueue.QueueState()}"); Console.WriteLine($"Cache size = {Count}"); } } finally { item_lock.Release(); } }
public LRUQueue() { Head = new CacheItemNode(default(String), null); Tail = new CacheItemNode(default(String), null); Head.Next = Tail; Tail.Previous = Head; }
public CacheItemNode RemoveLast() { CacheItemNode node = Tail.Previous; Tail.Previous = node.Previous; node.Previous.Next = Tail; node.Next = null; node.Previous = null; return(node); }
public CacheItemNode Remove(CacheItemNode node) { if (node.Next != null && node.Previous != null) { node.Previous.Next = node.Next; node.Next.Previous = node.Previous; } node.Next = null; node.Previous = null; return(node); }
public void MoveToFront(CacheItemNode node) { if (node.Next != null && node.Previous != null) { node.Previous.Next = node.Next; node.Next.Previous = node.Previous; } node.Next = Head.Next; Head.Next.Previous = node; node.Previous = Head; Head.Next = node; }
public string QueueState() { StringBuilder strb = new StringBuilder(); CacheItemNode node = Head.Next; while (node.Next != null) { if (node != null) { strb.Append($"{node.Key}:{node.Value.ToString()}, "); } node = node.Next; } return(strb.ToString()); }
public static void OnAdd(string key) { if (Count >= _capacity) { CacheItemNode cin = _lRUQueue.RemoveLast(); _memoryCache.Remove(cin.Key); // To ensure that we keep consistency between items in Cache // and in _locks dictionary, we remove the entry for the evited // key in _locks. if (!cin.Key.Equals(key)) { SemaphoreSlim semaphore; _locks.TryRemove(key, out semaphore); } } }
public bool TryGet(string key, out object result) { CacheItemNode cacheItemNode = null; if (_memoryCache.Contains(key)) { cacheItemNode = (CacheItemNode)_memoryCache[key]; _lRUQueue.MoveToFront(cacheItemNode); result = cacheItemNode.Value; return(true); } else { result = null; return(false); } }
public static void OnUpdate(CacheItemNode source, CacheItemNode updated) { Console.WriteLine($"Key Updated: {source.Key}, Item: (Original: {source.Value}, Updated: {updated.Value})"); }
public CacheItemNode(string key, object value) : base(key, value) { Previous = null; Next = null; }