2 * Copyright 2004-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
8 #include <util/OpenHashTable.h>
10 #include "AutoLocker.h"
15 template<typename Key
>
16 class HashSetElement
: public HashTableLink
<HashSetElement
<Key
> > {
18 typedef HashSetElement
<Key
> Element
;
27 HashSetElement(const Key
& key
)
37 // HashSetTableDefinition
38 template<typename Key
>
39 struct HashSetTableDefinition
{
41 typedef HashSetElement
<Key
> ValueType
;
43 size_t HashKey(const KeyType
& key
) const
44 { return key
.GetHashCode(); }
45 size_t Hash(const ValueType
* value
) const
46 { return HashKey(value
->fKey
); }
47 bool Compare(const KeyType
& key
, const ValueType
* value
) const
48 { return value
->fKey
== key
; }
49 HashTableLink
<ValueType
>* GetLink(ValueType
* value
) const
55 template<typename Key
>
60 typedef HashSetElement
<Key
> Element
;
62 Iterator(const Iterator
& other
)
65 fIterator(other
.fIterator
),
66 fElement(other
.fElement
)
72 return fIterator
.HasNext();
77 fElement
= fIterator
.Next();
81 return fElement
->fKey
;
89 fSet
->fTable
.RemoveUnchecked(fElement
);
96 Iterator
& operator=(const Iterator
& other
)
99 fIterator
= other
.fIterator
;
100 fElement
= other
.fElement
;
105 Iterator(HashSet
<Key
>* set
)
108 fIterator(set
->fTable
.GetIterator()),
114 friend class HashMap
<Key
, Value
>;
115 typedef OpenHashTable
<HashSetTableDefinition
<Key
> > ElementTable
;
118 ElementTable::Iterator fIterator
;
122 friend class HashSet
<Key
>;
128 status_t
InitCheck() const;
130 status_t
Add(const Key
& key
);
131 bool Remove(const Key
& key
);
133 bool Contains(const Key
& key
) const;
137 Iterator
GetIterator();
140 typedef OpenHashTable
<HashSetTableDefinition
<Key
> > ElementTable
;
141 typedef HashSetElement
<Key
> Element
;
142 friend class Iterator
;
149 // SynchronizedHashSet
150 template<typename Key
>
151 class SynchronizedHashSet
: public Locker
{
153 typedef HashSet
<Key
>::Iterator Iterator
;
155 SynchronizedHashSet() : Locker("synchronized hash set") {}
156 ~SynchronizedHashSet() { Lock(); }
158 status_t
InitCheck() const
160 return fSet
.InitCheck();
163 status_t
Add(const Key
& key
)
165 MapLocker
locker(this);
166 if (!locker
.IsLocked())
168 return fSet
.Add(key
);
171 bool Remove(const Key
& key
)
173 MapLocker
locker(this);
174 if (!locker
.IsLocked())
176 return fSet
.Remove(key
);
181 MapLocker
locker(this);
185 bool Contains(const Key
& key
) const
187 const Locker
* lock
= this;
188 MapLocker
locker(const_cast<Locker
*>(lock
));
189 if (!locker
.IsLocked())
191 return fSet
.Contains(key
);
196 const Locker
* lock
= this;
197 MapLocker
locker(const_cast<Locker
*>(lock
));
201 Iterator
GetIterator()
203 return fSet
.GetIterator();
206 // for debugging only
207 const HashSet
<Key
>& GetUnsynchronizedSet() const { return fSet
; }
208 HashSet
<Key
>& GetUnsynchronizedSet() { return fSet
; }
211 typedef AutoLocker
<Locker
> MapLocker
;
220 template<typename Key
>
221 HashSet
<Key
>::HashSet()
230 template<typename Key
>
231 HashSet
<Key
>::~HashSet()
238 template<typename Key
>
240 HashSet
<Key
>::InitCheck() const
242 return (fTable
.TableSize() > 0 ? B_OK
: B_NO_MEMORY
);
247 template<typename Key
>
249 HashSet
<Key
>::Add(const Key
& key
)
251 Element
* element
= fTable
.Lookup(key
);
253 // already contains the value
257 // does not contain the key yet: create an element and add it
258 element
= new(std::nothrow
) Element(key
);
262 status_t error
= fTable
.Insert(element
);
271 template<typename Key
>
273 HashSet
<Key
>::Remove(const Key
& key
)
275 Element
* element
= fTable
.Lookup(key
);
279 fTable
.Remove(element
);
287 template<typename Key
, typename Value
>
289 HashSet
<Key
>::Clear()
291 // clear the table and delete the elements
292 Element
* element
= fTable
.Clear(true);
293 while (element
!= NULL
) {
294 Element
* next
= element
->fNext
;
302 template<typename Key
>
304 HashSet
<Key
>::Contains(const Key
& key
) const
306 return fTable
.Lookup(key
) != NULL
;
311 template<typename Key
>
313 HashSet
<Key
>::Size() const
315 return fTable
.CountElements();
319 template<typename Key
>
320 HashSet
<Key
>::Iterator
321 HashSet
<Key
>::GetIterator()
323 return Iterator(this);
327 template<typename Key
>
328 HashSet
<Key
>::Element
*
329 HashSet
<Key
>::_FindElement(const Key
& key
) const
331 Element
* element
= fTable
.FindFirst(key
.GetHashCode());
332 while (element
&& element
->fKey
!= key
) {
333 if (element
->fNext
>= 0)
334 element
= fTable
.ElementAt(element
->fNext
);