2 * Copyright 2004-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
10 #include <util/OpenHashTable.h>
12 #include "AutoLocker.h"
17 template<typename Key
, typename Value
>
18 class HashMapElement
{
20 typedef HashMapElement
<Key
, Value
> Element
;
30 HashMapElement(const Key
& key
, const Value
& value
)
39 HashMapElement
* fNext
;
43 // HashMapTableDefinition
44 template<typename Key
, typename Value
>
45 struct HashMapTableDefinition
{
47 typedef HashMapElement
<Key
, Value
> ValueType
;
49 size_t HashKey(const KeyType
& key
) const
50 { return key
.GetHashCode(); }
51 size_t Hash(const ValueType
* value
) const
52 { return HashKey(value
->fKey
); }
53 bool Compare(const KeyType
& key
, const ValueType
* value
) const
54 { return value
->fKey
== key
; }
55 ValueType
*& GetLink(ValueType
* value
) const
56 { return value
->fNext
; }
61 template<typename Key
, typename Value
>
67 Entry(const Key
& key
, Value value
) : key(key
), value(value
) {}
75 typedef HashMapElement
<Key
, Value
> Element
;
77 Iterator(const Iterator
& other
)
80 fIterator(other
.fIterator
),
81 fElement(other
.fElement
)
87 return fIterator
.HasNext();
92 fElement
= fIterator
.Next();
96 return Entry(fElement
->fKey
, fElement
->fValue
);
101 if (fElement
== NULL
)
104 Entry
result(fElement
->fKey
, fElement
->fValue
);
106 fMap
->fTable
.RemoveUnchecked(fElement
);
113 Iterator
& operator=(const Iterator
& other
)
116 fIterator
= other
.fIterator
;
117 fElement
= other
.fElement
;
122 Iterator(HashMap
<Key
, Value
>* map
)
125 fIterator(map
->fTable
.GetIterator()),
131 friend class HashMap
<Key
, Value
>;
132 typedef BOpenHashTable
<HashMapTableDefinition
<Key
, Value
> >
135 HashMap
<Key
, Value
>* fMap
;
136 typename
ElementTable::Iterator fIterator
;
143 status_t
InitCheck() const;
145 status_t
Put(const Key
& key
, const Value
& value
);
146 Value
Remove(const Key
& key
);
148 Value
Get(const Key
& key
) const;
150 bool ContainsKey(const Key
& key
) const;
154 Iterator
GetIterator();
157 typedef BOpenHashTable
<HashMapTableDefinition
<Key
, Value
> > ElementTable
;
158 typedef HashMapElement
<Key
, Value
> Element
;
159 friend class Iterator
;
166 // SynchronizedHashMap
167 template<typename Key
, typename Value
>
168 class SynchronizedHashMap
: public Locker
{
170 typedef typename HashMap
<Key
, Value
>::Entry Entry
;
171 typedef typename HashMap
<Key
, Value
>::Iterator Iterator
;
173 SynchronizedHashMap() : Locker("synchronized hash map") {}
174 ~SynchronizedHashMap() { Lock(); }
176 status_t
InitCheck() const
178 return fMap
.InitCheck();
181 status_t
Put(const Key
& key
, const Value
& value
)
183 MapLocker
locker(this);
184 if (!locker
.IsLocked())
186 return fMap
.Put(key
, value
);
189 Value
Remove(const Key
& key
)
191 MapLocker
locker(this);
192 if (!locker
.IsLocked())
194 return fMap
.Remove(key
);
199 MapLocker
locker(this);
203 Value
Get(const Key
& key
) const
205 const Locker
* lock
= this;
206 MapLocker
locker(const_cast<Locker
*>(lock
));
207 if (!locker
.IsLocked())
209 return fMap
.Get(key
);
212 bool ContainsKey(const Key
& key
) const
214 const Locker
* lock
= this;
215 MapLocker
locker(const_cast<Locker
*>(lock
));
216 if (!locker
.IsLocked())
218 return fMap
.ContainsKey(key
);
223 const Locker
* lock
= this;
224 MapLocker
locker(const_cast<Locker
*>(lock
));
228 Iterator
GetIterator()
230 return fMap
.GetIterator();
233 // for debugging only
234 const HashMap
<Key
, Value
>& GetUnsynchronizedMap() const { return fMap
; }
235 HashMap
<Key
, Value
>& GetUnsynchronizedMap() { return fMap
; }
238 typedef AutoLocker
<Locker
> MapLocker
;
240 HashMap
<Key
, Value
> fMap
;
244 template<typename Value
>
247 HashKey32(const Value
& value
) : value(value
) {}
249 uint32
GetHashCode() const
251 return (uint32
)value
;
254 HashKey32
<Value
> operator=(const HashKey32
<Value
>& other
)
260 bool operator==(const HashKey32
<Value
>& other
) const
262 return (value
== other
.value
);
265 bool operator!=(const HashKey32
<Value
>& other
) const
267 return (value
!= other
.value
);
275 template<typename Value
>
278 HashKey64(const Value
& value
) : value(value
) {}
280 uint32
GetHashCode() const
282 uint64 v
= (uint64
)value
;
283 return (uint32
)(v
>> 32) ^ (uint32
)v
;
286 HashKey64
<Value
> operator=(const HashKey64
<Value
>& other
)
292 bool operator==(const HashKey64
<Value
>& other
) const
294 return (value
== other
.value
);
297 bool operator!=(const HashKey64
<Value
>& other
) const
299 return (value
!= other
.value
);
307 template<typename Value
>
308 struct HashKeyPointer
{
310 HashKeyPointer(const Value
& value
) : value(value
) {}
312 uint32
GetHashCode() const
314 #if __HAIKU_ARCH_BITS == 32
315 return (uint32
)(addr_t
)value
;
316 #elif __HAIKU_ARCH_BITS == 64
317 uint64 v
= (uint64
)(addr_t
)value
;
318 return (uint32
)(v
>> 32) ^ (uint32
)v
;
320 #error unknown bitness
324 HashKeyPointer
<Value
> operator=(const HashKeyPointer
<Value
>& other
)
330 bool operator==(const HashKeyPointer
<Value
>& other
) const
332 return (value
== other
.value
);
335 bool operator!=(const HashKeyPointer
<Value
>& other
) const
337 return (value
!= other
.value
);
347 template<typename Key
, typename Value
>
348 HashMap
<Key
, Value
>::HashMap()
357 template<typename Key
, typename Value
>
358 HashMap
<Key
, Value
>::~HashMap()
365 template<typename Key
, typename Value
>
367 HashMap
<Key
, Value
>::InitCheck() const
369 return (fTable
.TableSize() > 0 ? B_OK
: B_NO_MEMORY
);
374 template<typename Key
, typename Value
>
376 HashMap
<Key
, Value
>::Put(const Key
& key
, const Value
& value
)
378 Element
* element
= fTable
.Lookup(key
);
380 // already contains the key: just set the new value
381 element
->fValue
= value
;
385 // does not contain the key yet: create an element and add it
386 element
= new(std::nothrow
) Element(key
, value
);
390 status_t error
= fTable
.Insert(element
);
399 template<typename Key
, typename Value
>
401 HashMap
<Key
, Value
>::Remove(const Key
& key
)
403 Element
* element
= fTable
.Lookup(key
);
407 fTable
.Remove(element
);
408 Value value
= element
->fValue
;
416 template<typename Key
, typename Value
>
418 HashMap
<Key
, Value
>::Clear()
420 // clear the table and delete the elements
421 Element
* element
= fTable
.Clear(true);
422 while (element
!= NULL
) {
423 Element
* next
= element
->fNext
;
431 template<typename Key
, typename Value
>
433 HashMap
<Key
, Value
>::Get(const Key
& key
) const
435 if (Element
* element
= fTable
.Lookup(key
))
436 return element
->fValue
;
442 template<typename Key
, typename Value
>
444 HashMap
<Key
, Value
>::ContainsKey(const Key
& key
) const
446 return fTable
.Lookup(key
) != NULL
;
451 template<typename Key
, typename Value
>
453 HashMap
<Key
, Value
>::Size() const
455 return fTable
.CountElements();
460 template<typename Key
, typename Value
>
461 typename HashMap
<Key
, Value
>::Iterator
462 HashMap
<Key
, Value
>::GetIterator()
464 return Iterator(this);