HashTableSlim.cs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. using System;
  2. using System.Collections.Generic;
  3. namespace Ryujinx.Graphics.Vulkan
  4. {
  5. interface IRefEquatable<T>
  6. {
  7. bool Equals(ref T other);
  8. }
  9. class HashTableSlim<K, V> where K : IRefEquatable<K>
  10. {
  11. private const int TotalBuckets = 16; // Must be power of 2
  12. private const int TotalBucketsMask = TotalBuckets - 1;
  13. private struct Entry
  14. {
  15. public int Hash;
  16. public K Key;
  17. public V Value;
  18. }
  19. private readonly Entry[][] _hashTable = new Entry[TotalBuckets][];
  20. public IEnumerable<K> Keys
  21. {
  22. get
  23. {
  24. foreach (Entry[] bucket in _hashTable)
  25. {
  26. if (bucket != null)
  27. {
  28. foreach (Entry entry in bucket)
  29. {
  30. yield return entry.Key;
  31. }
  32. }
  33. }
  34. }
  35. }
  36. public IEnumerable<V> Values
  37. {
  38. get
  39. {
  40. foreach (Entry[] bucket in _hashTable)
  41. {
  42. if (bucket != null)
  43. {
  44. foreach (Entry entry in bucket)
  45. {
  46. yield return entry.Value;
  47. }
  48. }
  49. }
  50. }
  51. }
  52. public void Add(ref K key, V value)
  53. {
  54. var entry = new Entry()
  55. {
  56. Hash = key.GetHashCode(),
  57. Key = key,
  58. Value = value
  59. };
  60. int hashCode = key.GetHashCode();
  61. int bucketIndex = hashCode & TotalBucketsMask;
  62. var bucket = _hashTable[bucketIndex];
  63. if (bucket != null)
  64. {
  65. int index = bucket.Length;
  66. Array.Resize(ref _hashTable[bucketIndex], index + 1);
  67. _hashTable[bucketIndex][index] = entry;
  68. }
  69. else
  70. {
  71. _hashTable[bucketIndex] = new Entry[]
  72. {
  73. entry
  74. };
  75. }
  76. }
  77. public bool TryGetValue(ref K key, out V value)
  78. {
  79. int hashCode = key.GetHashCode();
  80. var bucket = _hashTable[hashCode & TotalBucketsMask];
  81. if (bucket != null)
  82. {
  83. for (int i = 0; i < bucket.Length; i++)
  84. {
  85. ref var entry = ref bucket[i];
  86. if (entry.Hash == hashCode && entry.Key.Equals(ref key))
  87. {
  88. value = entry.Value;
  89. return true;
  90. }
  91. }
  92. }
  93. value = default;
  94. return false;
  95. }
  96. }
  97. }