OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef SkTDynamicHash_DEFINED | 8 #ifndef SkTDynamicHash_DEFINED |
9 #define SkTDynamicHash_DEFINED | 9 #define SkTDynamicHash_DEFINED |
10 | 10 |
11 #include "SkTypes.h" | 11 #include "SkTypes.h" |
12 | 12 |
13 template <typename T, typename KEY, const KEY& (KEY_FROM_T)(const T&), | 13 template <typename T, |
14 uint32_t (HASH_FROM_KEY)(const Key&), bool (EQ_T_KEY)(const T&, const Key&)> | 14 typename KEY, |
15 const KEY& (KEY_FROM_T)(const T&), | |
16 uint32_t (HASH_FROM_KEY)(const KEY&), | |
17 bool (EQ_T_KEY)(const T&, const KEY&)> | |
15 class SkTDynamicHash { | 18 class SkTDynamicHash { |
16 private: | 19 private: |
17 T* fStorage[4]; | 20 T* fStorage[4]; // cheap storage for small arrays |
18 T** fArray; | 21 T** fArray; |
19 int fCapacity; | 22 int fCapacity; // number of slots in fArray. Must be pow2 |
20 int fCountUsed; | 23 int fCountUsed; // number of valid entries in fArray |
21 int fCountDeleted; | 24 int fCountDeleted; // number of deletedValue() entries in fArray |
22 | 25 |
26 // Need an illegal ptr value different from NULL (which we use to | |
27 // signal empty/unused. | |
mtklein
2013/07/29 18:51:22
add a ) ?
| |
23 const T* deletedValue() const { return reinterpret_cast<const T*>(-1); } | 28 const T* deletedValue() const { return reinterpret_cast<const T*>(-1); } |
29 | |
30 // fCapacity is a pow2, so that minus one is a clean mask to grab | |
31 // the low bits of hash to use as an index. | |
24 uint32_t hashMask() const { return fCapacity - 1; } | 32 uint32_t hashMask() const { return fCapacity - 1; } |
33 | |
25 int hashToIndex(uint32_t hash) const { | 34 int hashToIndex(uint32_t hash) const { |
26 return ((hash >> 16) ^ hash) & (fCapacity - 1); | 35 // this 16bit fold may be overkill, if we trust that hash is good |
36 return ((hash >> 16) ^ hash) & this->hashMask(); | |
27 } | 37 } |
38 | |
28 public: | 39 public: |
29 SkTDynamicHash() { | 40 SkTDynamicHash() { |
30 sk_bzero(fStorage, sizeof(fStorage)); | 41 sk_bzero(fStorage, sizeof(fStorage)); |
31 fArray = fStorage; | 42 fArray = fStorage; |
32 fCapacity = SK_ARRAY_COUNT(fStorage); | 43 fCapacity = SK_ARRAY_COUNT(fStorage); |
33 fCountUsed = fCountDeleted = 0; | 44 fCountUsed = fCountDeleted = 0; |
34 } | 45 } |
35 ~SkTDynamicHash() { | 46 ~SkTDynamicHash() { |
36 if (fArray != fStorage) { | 47 if (fArray != fStorage) { |
37 sk_free(fArray); | 48 sk_free(fArray); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
105 break; | 116 break; |
106 } | 117 } |
107 index = (index + delta) & mask; | 118 index = (index + delta) & mask; |
108 delta <<= 1; | 119 delta <<= 1; |
109 SkASSERT(delta <= fCapacity); | 120 SkASSERT(delta <= fCapacity); |
110 } | 121 } |
111 this->checkStrink(); | 122 this->checkStrink(); |
112 } | 123 } |
113 | 124 |
114 private: | 125 private: |
115 int countCollisions(const Key& key) const { | 126 int countCollisions(const KEY& key) const { |
116 const T* const deleted = this->deletedValue(); | 127 const T* const deleted = this->deletedValue(); |
117 const unsigned mask = this->hashMask(); | 128 const unsigned mask = this->hashMask(); |
118 int index = this->hashToIndex(HASH_FROM_KEY(key)); | 129 int index = this->hashToIndex(HASH_FROM_KEY(key)); |
119 int delta = 1; | 130 int delta = 1; |
120 int collisionCount = 0; | 131 int collisionCount = 0; |
121 | 132 |
122 for (;;) { | 133 for (;;) { |
123 const T* candidate = fArray[index]; | 134 const T* candidate = fArray[index]; |
124 SkASSERT(candidate); | 135 SkASSERT(candidate); |
125 if (deleted != candidate && EQ_T_KEY(*candidate, key)) { | 136 if (deleted != candidate && EQ_T_KEY(*candidate, key)) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
173 } | 184 } |
174 } | 185 } |
175 | 186 |
176 void checkStrink() { | 187 void checkStrink() { |
177 // todo: based on density and deadspace (fCountDeleted), consider | 188 // todo: based on density and deadspace (fCountDeleted), consider |
178 // shrinking fArray and repopulating it. | 189 // shrinking fArray and repopulating it. |
179 } | 190 } |
180 }; | 191 }; |
181 | 192 |
182 #endif | 193 #endif |
OLD | NEW |