Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace NWayCache
- {
- public class NWayCache<T1, T2>
- {
- private readonly int itemsPerSet;
- private readonly int numItems;
- private readonly int numSets;
- private Dictionary<int, Set> cache = new Dictionary<int, Set>();
- private Set[] cacheArray;
- public NWayCache(int itemsPerSet, int numItems)
- {
- this.itemsPerSet = itemsPerSet;
- this.numItems = numItems;
- if (numItems % itemsPerSet != 0) throw new DataMisalignedException("Number of items must be divisible by items per set");
- numSets = numItems / itemsPerSet;
- cacheArray = new Set[numSets];
- for (int i = 0; i < numSets; i++)
- {
- cacheArray[i] = new Set(itemsPerSet);
- }
- }
- public void SetEvictionLRU()
- {
- for (int i = 0; i < cacheArray.Length; i++)
- cacheArray[i].SetEvictionLRU();
- }
- public void SetEvictionMRU()
- {
- for (int i = 0; i < cacheArray.Length; i++)
- cacheArray[i].SetEvictionMRU();
- }
- public void SetEvictionCustomIndex(int index)
- {
- for (int i = 0; i < cacheArray.Length; i++)
- {
- cacheArray[i].SetEvictionCustomIndex(index);
- }
- }
- public T2 GetItem(T1 key)
- {
- int itemHash = Math.Abs(key.GetHashCode());
- int setNum = itemHash % numSets;
- return cacheArray[setNum].GetItem(key);
- }
- public void AddItem(T1 key, T2 value)
- {
- int itemHash = Math.Abs(key.GetHashCode());
- int setNum = itemHash % numSets;
- cacheArray[setNum].addItem(key, value);
- }
- private class Set
- {
- private Node head, tail;
- private readonly int setSize;
- private int replaceIndex;
- private delegate void EvictionMethod(T1 key, T2 value);
- private Dictionary<T1, Node> setData = new Dictionary<T1, Node>();
- private EvictionMethod evict;
- public Set(int setSize)
- {
- this.setSize = setSize;
- head = null;
- tail = null;
- evict = LruReplace;
- }
- public void SetEvictionLRU()
- {
- evict = LruReplace;
- }
- public void SetEvictionMRU()
- {
- evict = MruReplace;
- }
- public void SetEvictionCustomIndex(int index)
- {
- if (index > setSize - 1) throw new IndexOutOfRangeException();
- replaceIndex = index;
- evict = CustomReplace;
- }
- public void CustomReplace(T1 key, T2 value)
- {
- Node temp = tail;
- for (int i = 0; i < replaceIndex; i++)
- {
- temp = temp.prev;
- }
- MoveToTail(temp);
- setData.Remove(temp.key);
- MruReplace(key, value);
- }
- public T2 GetItem(T1 key)
- {
- if (setData.ContainsKey(key))
- {
- Node node = setData[key];
- MoveToTail(node);
- return node.value;
- }
- else return default(T2);
- }
- private void MoveToTail(Node node)
- {
- if (node != tail)
- {
- node.prev.next = node.next;
- node.next.prev = node.prev;
- node.next = tail.next;
- tail.next = node;
- node.prev = tail;
- head = node.next;
- head.prev = node;
- tail = node;
- }
- }
- public void LruReplace(T1 key, T2 value)
- {
- setData.Remove(head.key);
- Node node = new Node(key, value);
- tail.next = node;
- node.prev = tail;
- node.next = head.next;
- head = head.next;
- tail = node;
- head.prev = tail;
- }
- public void MruReplace(T1 key, T2 value)
- {
- setData.Remove(tail.key);
- Node node = new Node(key, value);
- head.prev = node;
- node.next = head;
- tail.prev.next = node;
- node.prev = tail.prev;
- tail = node;
- }
- public void addItem(T1 key, T2 value)
- {
- if (setData.Keys.Count >= setSize)
- {
- evict(key, value);
- setData.Add(key, tail);
- }
- else
- {
- Node node = new Node(key, value);
- if (head == null)
- {
- head = node;
- tail = head;
- }
- else
- {
- tail.next = node;
- node.prev = tail;
- node.next = head;
- head.prev = node;
- tail = node;
- head.prev = tail;
- }
- setData.Add(key, node);
- }
- }
- public int getSize() { return setSize; }
- private class Node
- {
- public T1 key;
- public T2 value;
- public Node prev, next;
- public Node(T1 key, T2 value)
- {
- this.key = key;
- this.value = value;
- prev = null;
- next = null;
- }
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement