DictionaryEntry.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. namespace JsUtil
  7. {
  8. namespace
  9. {
  10. template <class T1, class T2, bool isT1Smaller>
  11. struct ChooseSmallerHelper
  12. {
  13. typedef T2 type;
  14. };
  15. template <class T1, class T2>
  16. struct ChooseSmallerHelper<T1, T2, true>
  17. {
  18. typedef T1 type;
  19. };
  20. template <class T1, class T2>
  21. using ChooseSmaller = typename ChooseSmallerHelper<T1, T2, (sizeof(T1) < sizeof(T2))>::type;
  22. template <class TValue>
  23. class ValueEntryData
  24. {
  25. protected:
  26. TValue value; // data of entry
  27. public:
  28. int next; // Index of next entry, -1 if last
  29. };
  30. template <class TKey, class TValue>
  31. class KeyValueEntryDataLayout1
  32. {
  33. protected:
  34. TValue value; // data of entry
  35. TKey key; // key of entry
  36. public:
  37. int next; // Index of next entry, -1 if last
  38. };
  39. template <class TKey, class TValue>
  40. class KeyValueEntryDataLayout2
  41. {
  42. protected:
  43. TValue value; // data of entry
  44. public:
  45. int next; // Index of next entry, -1 if last
  46. protected:
  47. TKey key; // key of entry
  48. };
  49. // Packing matters because we make so many dictionary entries.
  50. // The int pointing to the next item in the list may be included
  51. // either after the value or after the key, depending on which
  52. // packs better.
  53. template <class TKey, class TValue>
  54. using KeyValueEntryData = ChooseSmaller<KeyValueEntryDataLayout1<TKey, TValue>, KeyValueEntryDataLayout2<TKey, TValue>>;
  55. template <class TValue, class TData = ValueEntryData<TValue>>
  56. class ValueEntry : public TData
  57. {
  58. protected:
  59. void Set(TValue const& value)
  60. {
  61. this->value = value;
  62. }
  63. public:
  64. static bool SupportsCleanup()
  65. {
  66. return false;
  67. }
  68. static bool NeedsCleanup(ValueEntry<TValue, TData>&)
  69. {
  70. return false;
  71. }
  72. void Clear()
  73. {
  74. ClearValue<TValue>::Clear(&this->value);
  75. }
  76. TValue const& Value() const { return this->value; }
  77. TValue& Value() { return this->value; }
  78. void SetValue(TValue const& value) { this->value = value; }
  79. };
  80. // Used by BaseHashSet, the default is that the key is the same as the value
  81. template <class TKey, class TValue>
  82. class ImplicitKeyValueEntry : public ValueEntry<TValue>
  83. {
  84. public:
  85. TKey Key() const { return ValueToKey<TKey, TValue>::ToKey(this->value); }
  86. void Set(TKey const& key, TValue const& value)
  87. {
  88. __super::Set(value);
  89. }
  90. };
  91. template <class TKey, class TValue>
  92. class KeyValueEntry : public ValueEntry<TValue, KeyValueEntryData<TKey, TValue>>
  93. {
  94. protected:
  95. void Set(TKey const& key, TValue const& value)
  96. {
  97. __super::Set(value);
  98. this->key = key;
  99. }
  100. public:
  101. TKey const& Key() const { return this->key; }
  102. void Clear()
  103. {
  104. __super::Clear();
  105. this->key = TKey();
  106. }
  107. };
  108. }
  109. template<class TKey, class TValue>
  110. struct ValueToKey
  111. {
  112. static TKey ToKey(const TValue &value) { return static_cast<TKey>(value); }
  113. };
  114. template <class TValue>
  115. struct ClearValue
  116. {
  117. static inline void Clear(TValue* value) { *value = TValue(); }
  118. };
  119. template <class TKey>
  120. class KeyEntry : public ValueEntry<TKey>
  121. {
  122. public:
  123. TKey const& Key() const { return this->value; }
  124. };
  125. template <class TKey, class TValue, template <class K, class V> class THashEntry>
  126. class DefaultHashedEntry : public THashEntry<TKey, TValue>
  127. {
  128. public:
  129. template<typename Comparer, typename TLookup>
  130. inline bool KeyEquals(TLookup const& otherKey, hash_t otherHashCode)
  131. {
  132. return Comparer::Equals(this->Key(), otherKey);
  133. }
  134. template<typename Comparer>
  135. inline hash_t GetHashCode()
  136. {
  137. return ((Comparer::GetHashCode(this->Key()) & 0x7fffffff) << 1) | 1;
  138. }
  139. void Set(TKey const& key, TValue const& value, int hashCode)
  140. {
  141. __super::Set(key, value);
  142. }
  143. };
  144. template <class TKey, template <class K> class THashKeyEntry>
  145. class DefaultHashedKeyEntry : public THashKeyEntry<TKey>
  146. {
  147. public:
  148. template<typename Comparer, typename TLookup>
  149. inline bool KeyEquals(TLookup const& otherKey, hash_t otherHashCode)
  150. {
  151. return Comparer::Equals(this->Key(), otherKey);
  152. }
  153. template<typename Comparer>
  154. inline hash_t GetHashCode()
  155. {
  156. return ((Comparer::GetHashCode(this->Key()) & 0x7fffffff) << 1) | 1;
  157. }
  158. void Set(TKey const& key, int hashCode)
  159. {
  160. __super::Set(key);
  161. }
  162. };
  163. template <class TKey, class TValue, template <class K, class V> class THashEntry>
  164. class CacheHashedEntry : public THashEntry<TKey, TValue>
  165. {
  166. hash_t hashCode; // Lower 31 bits of hash code << 1 | 1, 0 if unused
  167. public:
  168. static const int INVALID_HASH_VALUE = 0;
  169. template<typename Comparer, typename TLookup>
  170. inline bool KeyEquals(TLookup const& otherKey, hash_t otherHashCode)
  171. {
  172. Assert(TAGHASH(Comparer::GetHashCode(this->Key())) == this->hashCode);
  173. return this->hashCode == otherHashCode && Comparer::Equals(this->Key(), otherKey);
  174. }
  175. template<typename Comparer>
  176. inline hash_t GetHashCode()
  177. {
  178. Assert(TAGHASH(Comparer::GetHashCode(this->Key())) == this->hashCode);
  179. return hashCode;
  180. }
  181. void Set(TKey const& key, TValue const& value, hash_t hashCode)
  182. {
  183. __super::Set(key, value);
  184. this->hashCode = hashCode;
  185. }
  186. void Clear()
  187. {
  188. __super::Clear();
  189. this->hashCode = INVALID_HASH_VALUE;
  190. }
  191. };
  192. template <class TKey, class TValue>
  193. class SimpleHashedEntry : public DefaultHashedEntry<TKey, TValue, ImplicitKeyValueEntry> {};
  194. template <class TKey, class TValue>
  195. class HashedEntry : public CacheHashedEntry<TKey, TValue, ImplicitKeyValueEntry> {};
  196. template <class TKey, class TValue>
  197. class SimpleDictionaryEntry : public DefaultHashedEntry<TKey, TValue, KeyValueEntry> {};
  198. template <class TKey, class TValue>
  199. class DictionaryEntry: public CacheHashedEntry<TKey, TValue, KeyValueEntry> {};
  200. template <class TKey, class TValue>
  201. class WeakRefValueDictionaryEntry: public SimpleDictionaryEntry<TKey, TValue>
  202. {
  203. public:
  204. void Clear()
  205. {
  206. this->key = TKey();
  207. this->value = TValue();
  208. }
  209. static bool SupportsCleanup()
  210. {
  211. return true;
  212. }
  213. static bool NeedsCleanup(WeakRefValueDictionaryEntry<TKey, TValue> const& entry)
  214. {
  215. TValue weakReference = entry.Value();
  216. return (weakReference == nullptr || weakReference->Get() == nullptr);
  217. }
  218. };
  219. template <class TKey>
  220. class SimpleDictionaryKeyEntry : public DefaultHashedKeyEntry<TKey, KeyEntry> {};
  221. }