Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(178)

Side by Side Diff: src/base/hashmap.h

Issue 2343123002: [base] Template hashmap on key and value (Closed)
Patch Set: Initialise entries with placement new Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/base/hashmap-entry.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // The reason we write our own hash map instead of using unordered_map in STL, 5 // The reason we write our own hash map instead of using unordered_map in STL,
6 // is that STL containers use a mutex pool on debug build, which will lead to 6 // is that STL containers use a mutex pool on debug build, which will lead to
7 // deadlock when we are using async signal handler. 7 // deadlock when we are using async signal handler.
8 8
9 #ifndef V8_BASE_HASHMAP_H_ 9 #ifndef V8_BASE_HASHMAP_H_
10 #define V8_BASE_HASHMAP_H_ 10 #define V8_BASE_HASHMAP_H_
11 11
12 #include <stdlib.h> 12 #include <stdlib.h>
13 13
14 #include "src/base/bits.h" 14 #include "src/base/bits.h"
15 #include "src/base/hashmap-entry.h"
15 #include "src/base/logging.h" 16 #include "src/base/logging.h"
16 17
17 namespace v8 { 18 namespace v8 {
18 namespace base { 19 namespace base {
19 20
20 class DefaultAllocationPolicy { 21 class DefaultAllocationPolicy {
21 public: 22 public:
22 V8_INLINE void* New(size_t size) { return malloc(size); } 23 V8_INLINE void* New(size_t size) { return malloc(size); }
23 V8_INLINE static void Delete(void* p) { free(p); } 24 V8_INLINE static void Delete(void* p) { free(p); }
24 }; 25 };
25 26
26 template <class AllocationPolicy> 27 // Metaprogramming helper to allow pointer keys to be passed by value and
28 // non-pointer keys by const reference.
29 template <typename Key>
30 struct MatchFunHelper;
31
32 template <typename Key, typename Value, class AllocationPolicy>
27 class TemplateHashMapImpl { 33 class TemplateHashMapImpl {
28 public: 34 public:
29 typedef bool (*MatchFun)(void* key1, void* key2); 35 typedef typename MatchFunHelper<Key>::Fun MatchFun;
36 typedef TemplateHashMapEntry<Key, Value> Entry;
30 37
31 // The default capacity. This is used by the call sites which want 38 // The default capacity. This is used by the call sites which want
32 // to pass in a non-default AllocationPolicy but want to use the 39 // to pass in a non-default AllocationPolicy but want to use the
33 // default value of capacity specified by the implementation. 40 // default value of capacity specified by the implementation.
34 static const uint32_t kDefaultHashMapCapacity = 8; 41 static const uint32_t kDefaultHashMapCapacity = 8;
35 42
36 // initial_capacity is the size of the initial hash map; 43 // initial_capacity is the size of the initial hash map;
37 // it must be a power of 2 (and thus must not be 0). 44 // it must be a power of 2 (and thus must not be 0).
38 TemplateHashMapImpl(MatchFun match, 45 TemplateHashMapImpl(MatchFun match,
39 uint32_t capacity = kDefaultHashMapCapacity, 46 uint32_t capacity = kDefaultHashMapCapacity,
40 AllocationPolicy allocator = AllocationPolicy()); 47 AllocationPolicy allocator = AllocationPolicy());
41 48
42 ~TemplateHashMapImpl(); 49 ~TemplateHashMapImpl();
43 50
44 // HashMap entries are (key, value, hash) triplets.
45 // Some clients may not need to use the value slot
46 // (e.g. implementers of sets, where the key is the value).
47 struct Entry {
48 void* key;
49 void* value;
50 uint32_t hash; // The full hash value for key
51 };
52
53 // If an entry with matching key is found, returns that entry. 51 // If an entry with matching key is found, returns that entry.
54 // Otherwise, NULL is returned. 52 // Otherwise, nullptr is returned.
55 Entry* Lookup(void* key, uint32_t hash) const; 53 Entry* Lookup(const Key& key, uint32_t hash) const;
56 54
57 // If an entry with matching key is found, returns that entry. 55 // If an entry with matching key is found, returns that entry.
58 // If no matching entry is found, a new entry is inserted with 56 // If no matching entry is found, a new entry is inserted with
59 // corresponding key, key hash, and NULL value. 57 // corresponding key, key hash, and default initialized value.
60 Entry* LookupOrInsert(void* key, uint32_t hash, 58 Entry* LookupOrInsert(const Key& key, uint32_t hash,
61 AllocationPolicy allocator = AllocationPolicy()); 59 AllocationPolicy allocator = AllocationPolicy());
62 60
63 Entry* InsertNew(void* key, uint32_t hash, 61 Entry* InsertNew(const Key& key, uint32_t hash,
64 AllocationPolicy allocator = AllocationPolicy()); 62 AllocationPolicy allocator = AllocationPolicy());
65 63
66 // Removes the entry with matching key. 64 // Removes the entry with matching key.
67 // It returns the value of the deleted entry 65 // It returns the value of the deleted entry
68 // or null if there is no value for such key. 66 // or null if there is no value for such key.
69 void* Remove(void* key, uint32_t hash); 67 Value Remove(const Key& key, uint32_t hash);
70 68
71 // Empties the hash map (occupancy() == 0). 69 // Empties the hash map (occupancy() == 0).
72 void Clear(); 70 void Clear();
73 71
74 // The number of (non-empty) entries in the table. 72 // The number of (non-empty) entries in the table.
75 uint32_t occupancy() const { return occupancy_; } 73 uint32_t occupancy() const { return occupancy_; }
76 74
77 // The capacity of the table. The implementation 75 // The capacity of the table. The implementation
78 // makes sure that occupancy is at most 80% of 76 // makes sure that occupancy is at most 80% of
79 // the table capacity. 77 // the table capacity.
80 uint32_t capacity() const { return capacity_; } 78 uint32_t capacity() const { return capacity_; }
81 79
82 // Iteration 80 // Iteration
83 // 81 //
84 // for (Entry* p = map.Start(); p != NULL; p = map.Next(p)) { 82 // for (Entry* p = map.Start(); p != nullptr; p = map.Next(p)) {
85 // ... 83 // ...
86 // } 84 // }
87 // 85 //
88 // If entries are inserted during iteration, the effect of 86 // If entries are inserted during iteration, the effect of
89 // calling Next() is undefined. 87 // calling Next() is undefined.
90 Entry* Start() const; 88 Entry* Start() const;
91 Entry* Next(Entry* p) const; 89 Entry* Next(Entry* p) const;
92 90
93 // Some match functions defined for convenience. 91 // Some match functions defined for convenience.
94 static bool PointersMatch(void* key1, void* key2) { return key1 == key2; } 92 static bool PointersMatch(typename MatchFunHelper<Key>::KeyRef key1,
rmcilroy 2016/09/19 10:32:07 Hmm, this isn't really PointersMatch unless Key is
Leszek Swirski 2016/09/19 10:45:33 Added a TODO because I want to move the matcher fu
93 typename MatchFunHelper<Key>::KeyRef key2) {
94 return key1 == key2;
95 }
95 96
96 private: 97 private:
97 MatchFun match_; 98 MatchFun match_;
98 Entry* map_; 99 Entry* map_;
99 uint32_t capacity_; 100 uint32_t capacity_;
100 uint32_t occupancy_; 101 uint32_t occupancy_;
101 102
102 Entry* map_end() const { return map_ + capacity_; } 103 Entry* map_end() const { return map_ + capacity_; }
103 Entry* Probe(void* key, uint32_t hash) const; 104 Entry* Probe(const Key& key, uint32_t hash) const;
104 void Initialize(uint32_t capacity, AllocationPolicy allocator); 105 void Initialize(uint32_t capacity, AllocationPolicy allocator);
105 void Resize(AllocationPolicy allocator); 106 void Resize(AllocationPolicy allocator);
106 }; 107 };
107 108
108 typedef TemplateHashMapImpl<DefaultAllocationPolicy> HashMap; 109 template <typename Key>
110 struct MatchFunHelper {
111 typedef const Key& KeyRef;
112 typedef bool (*Fun)(KeyRef key1, KeyRef key2);
113 };
109 114
110 template <class AllocationPolicy> 115 template <typename Key>
111 TemplateHashMapImpl<AllocationPolicy>::TemplateHashMapImpl( 116 struct MatchFunHelper<Key*> {
117 typedef Key* KeyRef;
118 typedef bool (*Fun)(KeyRef key1, KeyRef key2);
119 };
120
121 typedef TemplateHashMapImpl<void*, void*, DefaultAllocationPolicy> HashMap;
122
123 template <typename Key, typename Value, class AllocationPolicy>
124 TemplateHashMapImpl<Key, Value, AllocationPolicy>::TemplateHashMapImpl(
112 MatchFun match, uint32_t initial_capacity, AllocationPolicy allocator) { 125 MatchFun match, uint32_t initial_capacity, AllocationPolicy allocator) {
113 match_ = match; 126 match_ = match;
114 Initialize(initial_capacity, allocator); 127 Initialize(initial_capacity, allocator);
115 } 128 }
116 129
117 template <class AllocationPolicy> 130 template <typename Key, typename Value, class AllocationPolicy>
118 TemplateHashMapImpl<AllocationPolicy>::~TemplateHashMapImpl() { 131 TemplateHashMapImpl<Key, Value, AllocationPolicy>::~TemplateHashMapImpl() {
119 AllocationPolicy::Delete(map_); 132 AllocationPolicy::Delete(map_);
120 } 133 }
121 134
122 template <class AllocationPolicy> 135 template <typename Key, typename Value, class AllocationPolicy>
123 typename TemplateHashMapImpl<AllocationPolicy>::Entry* 136 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry*
124 TemplateHashMapImpl<AllocationPolicy>::Lookup(void* key, uint32_t hash) const { 137 TemplateHashMapImpl<Key, Value, AllocationPolicy>::Lookup(const Key& key,
138 uint32_t hash) const {
125 Entry* p = Probe(key, hash); 139 Entry* p = Probe(key, hash);
126 return p->key != NULL ? p : NULL; 140 return p->exists() ? p : nullptr;
127 } 141 }
128 142
129 template <class AllocationPolicy> 143 template <typename Key, typename Value, class AllocationPolicy>
130 typename TemplateHashMapImpl<AllocationPolicy>::Entry* 144 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry*
131 TemplateHashMapImpl<AllocationPolicy>::LookupOrInsert( 145 TemplateHashMapImpl<Key, Value, AllocationPolicy>::LookupOrInsert(
132 void* key, uint32_t hash, AllocationPolicy allocator) { 146 const Key& key, uint32_t hash, AllocationPolicy allocator) {
133 // Find a matching entry. 147 // Find a matching entry.
134 Entry* p = Probe(key, hash); 148 Entry* p = Probe(key, hash);
135 if (p->key != NULL) { 149 if (p->exists()) {
136 return p; 150 return p;
137 } 151 }
138 152
139 return InsertNew(key, hash, allocator); 153 return InsertNew(key, hash, allocator);
140 } 154 }
141 155
142 template <class AllocationPolicy> 156 template <typename Key, typename Value, class AllocationPolicy>
143 typename TemplateHashMapImpl<AllocationPolicy>::Entry* 157 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry*
144 TemplateHashMapImpl<AllocationPolicy>::InsertNew(void* key, uint32_t hash, 158 TemplateHashMapImpl<Key, Value, AllocationPolicy>::InsertNew(
145 AllocationPolicy allocator) { 159 const Key& key, uint32_t hash, AllocationPolicy allocator) {
146 // Find a matching entry. 160 // Find a matching entry.
147 Entry* p = Probe(key, hash); 161 Entry* p = Probe(key, hash);
148 DCHECK(p->key == NULL); 162 DCHECK(!p->exists());
149 163
150 // No entry found; insert one. 164 // No entry found; insert one.
151 p->key = key; 165 new (p) Entry(key, Value(), hash);
rmcilroy 2016/09/19 10:32:07 Could you add a comment that this is in-placement
Leszek Swirski 2016/09/19 10:45:33 Done.
152 p->value = NULL;
153 p->hash = hash;
154 occupancy_++; 166 occupancy_++;
155 167
156 // Grow the map if we reached >= 80% occupancy. 168 // Grow the map if we reached >= 80% occupancy.
157 if (occupancy_ + occupancy_ / 4 >= capacity_) { 169 if (occupancy_ + occupancy_ / 4 >= capacity_) {
158 Resize(allocator); 170 Resize(allocator);
159 p = Probe(key, hash); 171 p = Probe(key, hash);
160 } 172 }
161 173
162 return p; 174 return p;
163 } 175 }
164 176
165 template <class AllocationPolicy> 177 template <typename Key, typename Value, class AllocationPolicy>
166 void* TemplateHashMapImpl<AllocationPolicy>::Remove(void* key, uint32_t hash) { 178 Value TemplateHashMapImpl<Key, Value, AllocationPolicy>::Remove(const Key& key,
179 uint32_t hash) {
167 // Lookup the entry for the key to remove. 180 // Lookup the entry for the key to remove.
168 Entry* p = Probe(key, hash); 181 Entry* p = Probe(key, hash);
169 if (p->key == NULL) { 182 if (!p->exists()) {
170 // Key not found nothing to remove. 183 // Key not found nothing to remove.
171 return NULL; 184 return nullptr;
172 } 185 }
173 186
174 void* value = p->value; 187 Value value = p->value;
175 // To remove an entry we need to ensure that it does not create an empty 188 // To remove an entry we need to ensure that it does not create an empty
176 // entry that will cause the search for another entry to stop too soon. If all 189 // entry that will cause the search for another entry to stop too soon. If all
177 // the entries between the entry to remove and the next empty slot have their 190 // the entries between the entry to remove and the next empty slot have their
178 // initial position inside this interval, clearing the entry to remove will 191 // initial position inside this interval, clearing the entry to remove will
179 // not break the search. If, while searching for the next empty entry, an 192 // not break the search. If, while searching for the next empty entry, an
180 // entry is encountered which does not have its initial position between the 193 // entry is encountered which does not have its initial position between the
181 // entry to remove and the position looked at, then this entry can be moved to 194 // entry to remove and the position looked at, then this entry can be moved to
182 // the place of the entry to remove without breaking the search for it. The 195 // the place of the entry to remove without breaking the search for it. The
183 // entry made vacant by this move is now the entry to remove and the process 196 // entry made vacant by this move is now the entry to remove and the process
184 // starts over. 197 // starts over.
185 // Algorithm from http://en.wikipedia.org/wiki/Open_addressing. 198 // Algorithm from http://en.wikipedia.org/wiki/Open_addressing.
186 199
187 // This guarantees loop termination as there is at least one empty entry so 200 // This guarantees loop termination as there is at least one empty entry so
188 // eventually the removed entry will have an empty entry after it. 201 // eventually the removed entry will have an empty entry after it.
189 DCHECK(occupancy_ < capacity_); 202 DCHECK(occupancy_ < capacity_);
190 203
191 // p is the candidate entry to clear. q is used to scan forwards. 204 // p is the candidate entry to clear. q is used to scan forwards.
192 Entry* q = p; // Start at the entry to remove. 205 Entry* q = p; // Start at the entry to remove.
193 while (true) { 206 while (true) {
194 // Move q to the next entry. 207 // Move q to the next entry.
195 q = q + 1; 208 q = q + 1;
196 if (q == map_end()) { 209 if (q == map_end()) {
197 q = map_; 210 q = map_;
198 } 211 }
199 212
200 // All entries between p and q have their initial position between p and q 213 // All entries between p and q have their initial position between p and q
201 // and the entry p can be cleared without breaking the search for these 214 // and the entry p can be cleared without breaking the search for these
202 // entries. 215 // entries.
203 if (q->key == NULL) { 216 if (!q->exists()) {
204 break; 217 break;
205 } 218 }
206 219
207 // Find the initial position for the entry at position q. 220 // Find the initial position for the entry at position q.
208 Entry* r = map_ + (q->hash & (capacity_ - 1)); 221 Entry* r = map_ + (q->hash & (capacity_ - 1));
209 222
210 // If the entry at position q has its initial position outside the range 223 // If the entry at position q has its initial position outside the range
211 // between p and q it can be moved forward to position p and will still be 224 // between p and q it can be moved forward to position p and will still be
212 // found. There is now a new candidate entry for clearing. 225 // found. There is now a new candidate entry for clearing.
213 if ((q > p && (r <= p || r > q)) || (q < p && (r <= p && r > q))) { 226 if ((q > p && (r <= p || r > q)) || (q < p && (r <= p && r > q))) {
214 *p = *q; 227 *p = *q;
215 p = q; 228 p = q;
216 } 229 }
217 } 230 }
218 231
219 // Clear the entry which is allowed to en emptied. 232 // Clear the entry which is allowed to en emptied.
220 p->key = NULL; 233 p->clear();
221 occupancy_--; 234 occupancy_--;
222 return value; 235 return value;
223 } 236 }
224 237
225 template <class AllocationPolicy> 238 template <typename Key, typename Value, class AllocationPolicy>
226 void TemplateHashMapImpl<AllocationPolicy>::Clear() { 239 void TemplateHashMapImpl<Key, Value, AllocationPolicy>::Clear() {
227 // Mark all entries as empty. 240 // Mark all entries as empty.
228 const Entry* end = map_end(); 241 const Entry* end = map_end();
229 for (Entry* p = map_; p < end; p++) { 242 for (Entry* p = map_; p < end; p++) {
230 p->key = NULL; 243 p->clear();
231 } 244 }
232 occupancy_ = 0; 245 occupancy_ = 0;
233 } 246 }
234 247
235 template <class AllocationPolicy> 248 template <typename Key, typename Value, class AllocationPolicy>
236 typename TemplateHashMapImpl<AllocationPolicy>::Entry* 249 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry*
237 TemplateHashMapImpl<AllocationPolicy>::Start() const { 250 TemplateHashMapImpl<Key, Value, AllocationPolicy>::Start() const {
238 return Next(map_ - 1); 251 return Next(map_ - 1);
239 } 252 }
240 253
241 template <class AllocationPolicy> 254 template <typename Key, typename Value, class AllocationPolicy>
242 typename TemplateHashMapImpl<AllocationPolicy>::Entry* 255 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry*
243 TemplateHashMapImpl<AllocationPolicy>::Next(Entry* p) const { 256 TemplateHashMapImpl<Key, Value, AllocationPolicy>::Next(Entry* p) const {
244 const Entry* end = map_end(); 257 const Entry* end = map_end();
245 DCHECK(map_ - 1 <= p && p < end); 258 DCHECK(map_ - 1 <= p && p < end);
246 for (p++; p < end; p++) { 259 for (p++; p < end; p++) {
247 if (p->key != NULL) { 260 if (p->exists()) {
248 return p; 261 return p;
249 } 262 }
250 } 263 }
251 return NULL; 264 return nullptr;
252 } 265 }
253 266
254 template <class AllocationPolicy> 267 template <typename Key, typename Value, class AllocationPolicy>
255 typename TemplateHashMapImpl<AllocationPolicy>::Entry* 268 typename TemplateHashMapImpl<Key, Value, AllocationPolicy>::Entry*
256 TemplateHashMapImpl<AllocationPolicy>::Probe(void* key, uint32_t hash) const { 269 TemplateHashMapImpl<Key, Value, AllocationPolicy>::Probe(const Key& key,
257 DCHECK(key != NULL); 270 uint32_t hash) const {
258
259 DCHECK(base::bits::IsPowerOfTwo32(capacity_)); 271 DCHECK(base::bits::IsPowerOfTwo32(capacity_));
260 Entry* p = map_ + (hash & (capacity_ - 1)); 272 Entry* p = map_ + (hash & (capacity_ - 1));
261 const Entry* end = map_end(); 273 const Entry* end = map_end();
262 DCHECK(map_ <= p && p < end); 274 DCHECK(map_ <= p && p < end);
263 275
264 DCHECK(occupancy_ < capacity_); // Guarantees loop termination. 276 DCHECK(occupancy_ < capacity_); // Guarantees loop termination.
265 while (p->key != NULL && (hash != p->hash || !match_(key, p->key))) { 277 while (p->exists() && (hash != p->hash || !match_(key, p->key))) {
266 p++; 278 p++;
267 if (p >= end) { 279 if (p >= end) {
268 p = map_; 280 p = map_;
269 } 281 }
270 } 282 }
271 283
272 return p; 284 return p;
273 } 285 }
274 286
275 template <class AllocationPolicy> 287 template <typename Key, typename Value, class AllocationPolicy>
276 void TemplateHashMapImpl<AllocationPolicy>::Initialize( 288 void TemplateHashMapImpl<Key, Value, AllocationPolicy>::Initialize(
277 uint32_t capacity, AllocationPolicy allocator) { 289 uint32_t capacity, AllocationPolicy allocator) {
278 DCHECK(base::bits::IsPowerOfTwo32(capacity)); 290 DCHECK(base::bits::IsPowerOfTwo32(capacity));
279 map_ = reinterpret_cast<Entry*>(allocator.New(capacity * sizeof(Entry))); 291 map_ = reinterpret_cast<Entry*>(allocator.New(capacity * sizeof(Entry)));
280 if (map_ == NULL) { 292 if (map_ == nullptr) {
281 FATAL("Out of memory: HashMap::Initialize"); 293 FATAL("Out of memory: HashMap::Initialize");
282 return; 294 return;
283 } 295 }
284 capacity_ = capacity; 296 capacity_ = capacity;
285 Clear(); 297 Clear();
286 } 298 }
287 299
288 template <class AllocationPolicy> 300 template <typename Key, typename Value, class AllocationPolicy>
289 void TemplateHashMapImpl<AllocationPolicy>::Resize(AllocationPolicy allocator) { 301 void TemplateHashMapImpl<Key, Value, AllocationPolicy>::Resize(
302 AllocationPolicy allocator) {
290 Entry* map = map_; 303 Entry* map = map_;
291 uint32_t n = occupancy_; 304 uint32_t n = occupancy_;
292 305
293 // Allocate larger map. 306 // Allocate larger map.
294 Initialize(capacity_ * 2, allocator); 307 Initialize(capacity_ * 2, allocator);
295 308
296 // Rehash all current entries. 309 // Rehash all current entries.
297 for (Entry* p = map; n > 0; p++) { 310 for (Entry* p = map; n > 0; p++) {
298 if (p->key != NULL) { 311 if (p->exists()) {
299 Entry* entry = LookupOrInsert(p->key, p->hash, allocator); 312 Entry* entry = LookupOrInsert(p->key, p->hash, allocator);
300 entry->value = p->value; 313 entry->value = p->value;
301 n--; 314 n--;
302 } 315 }
303 } 316 }
304 317
305 // Delete old map. 318 // Delete old map.
306 AllocationPolicy::Delete(map); 319 AllocationPolicy::Delete(map);
307 } 320 }
308 321
309 // A hash map for pointer keys and values with an STL-like interface. 322 // A hash map for pointer keys and values with an STL-like interface.
310 template <class Key, class Value, class AllocationPolicy> 323 template <class Key, class Value, class AllocationPolicy>
311 class TemplateHashMap : private TemplateHashMapImpl<AllocationPolicy> { 324 class TemplateHashMap
325 : private TemplateHashMapImpl<void*, void*, AllocationPolicy> {
312 public: 326 public:
313 STATIC_ASSERT(sizeof(Key*) == sizeof(void*)); // NOLINT 327 STATIC_ASSERT(sizeof(Key*) == sizeof(void*)); // NOLINT
314 STATIC_ASSERT(sizeof(Value*) == sizeof(void*)); // NOLINT 328 STATIC_ASSERT(sizeof(Value*) == sizeof(void*)); // NOLINT
315 struct value_type { 329 struct value_type {
316 Key* first; 330 Key* first;
317 Value* second; 331 Value* second;
318 }; 332 };
319 333
320 class Iterator { 334 class Iterator {
321 public: 335 public:
322 Iterator& operator++() { 336 Iterator& operator++() {
323 entry_ = map_->Next(entry_); 337 entry_ = map_->Next(entry_);
324 return *this; 338 return *this;
325 } 339 }
326 340
327 value_type* operator->() { return reinterpret_cast<value_type*>(entry_); } 341 value_type* operator->() { return reinterpret_cast<value_type*>(entry_); }
328 bool operator!=(const Iterator& other) { return entry_ != other.entry_; } 342 bool operator!=(const Iterator& other) { return entry_ != other.entry_; }
329 343
330 private: 344 private:
331 Iterator(const TemplateHashMapImpl<AllocationPolicy>* map, 345 Iterator(const TemplateHashMapImpl<void*, void*, AllocationPolicy>* map,
332 typename TemplateHashMapImpl<AllocationPolicy>::Entry* entry) 346 typename TemplateHashMapImpl<void*, void*,
347 AllocationPolicy>::Entry* entry)
333 : map_(map), entry_(entry) {} 348 : map_(map), entry_(entry) {}
334 349
335 const TemplateHashMapImpl<AllocationPolicy>* map_; 350 const TemplateHashMapImpl<void*, void*, AllocationPolicy>* map_;
336 typename TemplateHashMapImpl<AllocationPolicy>::Entry* entry_; 351 typename TemplateHashMapImpl<void*, void*, AllocationPolicy>::Entry* entry_;
337 352
338 friend class TemplateHashMap; 353 friend class TemplateHashMap;
339 }; 354 };
340 355
341 TemplateHashMap( 356 TemplateHashMap(typename TemplateHashMapImpl<
342 typename TemplateHashMapImpl<AllocationPolicy>::MatchFun match, 357 void*, void*, AllocationPolicy>::MatchFun match,
343 AllocationPolicy allocator = AllocationPolicy()) 358 AllocationPolicy allocator = AllocationPolicy())
344 : TemplateHashMapImpl<AllocationPolicy>( 359 : TemplateHashMapImpl<void*, void*, AllocationPolicy>(
345 match, 360 match,
346 TemplateHashMapImpl<AllocationPolicy>::kDefaultHashMapCapacity, 361 TemplateHashMapImpl<void*, void*,
362 AllocationPolicy>::kDefaultHashMapCapacity,
347 allocator) {} 363 allocator) {}
348 364
349 Iterator begin() const { return Iterator(this, this->Start()); } 365 Iterator begin() const { return Iterator(this, this->Start()); }
350 Iterator end() const { return Iterator(this, NULL); } 366 Iterator end() const { return Iterator(this, nullptr); }
351 Iterator find(Key* key, bool insert = false, 367 Iterator find(Key* key, bool insert = false,
352 AllocationPolicy allocator = AllocationPolicy()) { 368 AllocationPolicy allocator = AllocationPolicy()) {
353 if (insert) { 369 if (insert) {
354 return Iterator(this, this->LookupOrInsert(key, key->Hash(), allocator)); 370 return Iterator(this, this->LookupOrInsert(key, key->Hash(), allocator));
355 } 371 }
356 return Iterator(this, this->Lookup(key, key->Hash())); 372 return Iterator(this, this->Lookup(key, key->Hash()));
357 } 373 }
358 }; 374 };
359 375
360 } // namespace base 376 } // namespace base
361 } // namespace v8 377 } // namespace v8
362 378
363 #endif // V8_BASE_HASHMAP_H_ 379 #endif // V8_BASE_HASHMAP_H_
OLDNEW
« no previous file with comments | « no previous file | src/base/hashmap-entry.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698