diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Vulkan/HashTableSlim.cs')
-rw-r--r-- | src/Ryujinx.Graphics.Vulkan/HashTableSlim.cs | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Vulkan/HashTableSlim.cs b/src/Ryujinx.Graphics.Vulkan/HashTableSlim.cs new file mode 100644 index 00000000..e4ad3958 --- /dev/null +++ b/src/Ryujinx.Graphics.Vulkan/HashTableSlim.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; + +namespace Ryujinx.Graphics.Vulkan +{ + interface IRefEquatable<T> + { + bool Equals(ref T other); + } + + class HashTableSlim<K, V> where K : IRefEquatable<K> + { + private const int TotalBuckets = 16; // Must be power of 2 + private const int TotalBucketsMask = TotalBuckets - 1; + + private struct Entry + { + public int Hash; + public K Key; + public V Value; + } + + private readonly Entry[][] _hashTable = new Entry[TotalBuckets][]; + + public IEnumerable<K> Keys + { + get + { + foreach (Entry[] bucket in _hashTable) + { + if (bucket != null) + { + foreach (Entry entry in bucket) + { + yield return entry.Key; + } + } + } + } + } + + public IEnumerable<V> Values + { + get + { + foreach (Entry[] bucket in _hashTable) + { + if (bucket != null) + { + foreach (Entry entry in bucket) + { + yield return entry.Value; + } + } + } + } + } + + public void Add(ref K key, V value) + { + var entry = new Entry() + { + Hash = key.GetHashCode(), + Key = key, + Value = value + }; + + int hashCode = key.GetHashCode(); + int bucketIndex = hashCode & TotalBucketsMask; + + var bucket = _hashTable[bucketIndex]; + if (bucket != null) + { + int index = bucket.Length; + + Array.Resize(ref _hashTable[bucketIndex], index + 1); + + _hashTable[bucketIndex][index] = entry; + } + else + { + _hashTable[bucketIndex] = new Entry[] + { + entry + }; + } + } + + public bool TryGetValue(ref K key, out V value) + { + int hashCode = key.GetHashCode(); + + var bucket = _hashTable[hashCode & TotalBucketsMask]; + if (bucket != null) + { + for (int i = 0; i < bucket.Length; i++) + { + ref var entry = ref bucket[i]; + + if (entry.Hash == hashCode && entry.Key.Equals(ref key)) + { + value = entry.Value; + return true; + } + } + } + + value = default; + return false; + } + } +} |