Chromium Code Reviews| 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 |