3 // Copyright (c) 2004, Ingo Weinhold (bonefish@cs.tu-berlin.de)
5 // Permission is hereby granted, free of charge, to any person obtaining a
6 // copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following conditions:
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 // DEALINGS IN THE SOFTWARE.
23 // Except as contained in this notice, the name of a copyright holder shall
24 // not be used in advertising or otherwise to promote the sale, use or other
25 // dealings in this Software without prior written authorization of the
33 #include "AutoLocker.h"
34 #include "OpenHashTable.h"
40 template<typename Key
>
41 class HashSetElement
: public OpenHashElement
{
43 typedef HashSetElement
<Key
> Element
;
46 HashSetElement() : OpenHashElement(), fKey()
51 inline uint32
Hash() const
53 return fKey
.GetHashCode();
56 inline bool operator==(const OpenHashElement
&_element
) const
58 const Element
&element
= static_cast<const Element
&>(_element
);
59 return (fKey
== element
.fKey
);
62 inline void Adopt(Element
&element
)
71 template<typename Key
>
76 typedef HashSetElement
<Key
> Element
;
78 Iterator(const Iterator
& other
)
81 fElement(other
.fElement
),
82 fLastElement(other
.fElement
)
95 Key
result(fElement
->fKey
);
104 fSet
->fTable
.Remove(fLastElement
);
109 Iterator
& operator=(const Iterator
& other
)
112 fIndex
= other
.fIndex
;
113 fElement
= other
.fElement
;
114 fLastElement
= other
.fLastElement
;
119 Iterator(HashSet
<Key
>* map
)
131 fLastElement
= fElement
;
132 if (fElement
&& fElement
->fNext
>= 0) {
133 fElement
= fSet
->fTable
.ElementAt(fElement
->fNext
);
137 int32 arraySize
= fSet
->fTable
.ArraySize();
138 for (; !fElement
&& fIndex
< arraySize
; fIndex
++)
139 fElement
= fSet
->fTable
.FindFirst(fIndex
);
143 friend class HashSet
<Key
>;
148 Element
* fLastElement
;
154 status_t
InitCheck() const;
156 status_t
Add(const Key
& key
);
157 bool Remove(const Key
& key
);
159 bool Contains(const Key
& key
) const;
162 bool IsEmpty() const { return Size() == 0; }
164 Iterator
GetIterator();
167 typedef HashSetElement
<Key
> Element
;
168 friend class Iterator
;
171 Element
*_FindElement(const Key
& key
) const;
174 OpenHashElementArray
<Element
> fElementArray
;
175 OpenHashTable
<Element
, OpenHashElementArray
<Element
> > fTable
;
178 // SynchronizedHashSet
179 template<typename Key
>
180 class SynchronizedHashSet
: public BLocker
{
182 typedef typename HashSet
<Key
>::Iterator Iterator
;
184 SynchronizedHashSet() : BLocker("synchronized hash set") {}
185 ~SynchronizedHashSet() { Lock(); }
187 status_t
InitCheck() const
189 return fSet
.InitCheck();
192 status_t
Add(const Key
& key
)
194 MapLocker
locker(this);
195 if (!locker
.IsLocked())
197 return fSet
.Add(key
);
200 bool Remove(const Key
& key
)
202 MapLocker
locker(this);
203 if (!locker
.IsLocked())
205 return fSet
.Remove(key
);
208 bool Contains(const Key
& key
) const
210 const BLocker
* lock
= this;
211 MapLocker
locker(const_cast<BLocker
*>(lock
));
212 if (!locker
.IsLocked())
214 return fSet
.Contains(key
);
219 const BLocker
* lock
= this;
220 MapLocker
locker(const_cast<BLocker
*>(lock
));
224 Iterator
GetIterator()
226 return fSet
.GetIterator();
229 // for debugging only
230 const HashSet
<Key
>& GetUnsynchronizedSet() const { return fSet
; }
231 HashSet
<Key
>& GetUnsynchronizedSet() { return fSet
; }
234 typedef AutoLocker
<BLocker
> MapLocker
;
242 template<typename Key
>
243 HashSet
<Key
>::HashSet()
244 : fElementArray(1000),
245 fTable(1000, &fElementArray
)
250 template<typename Key
>
251 HashSet
<Key
>::~HashSet()
256 template<typename Key
>
258 HashSet
<Key
>::InitCheck() const
260 return (fTable
.InitCheck() && fElementArray
.InitCheck()
261 ? B_OK
: B_NO_MEMORY
);
265 template<typename Key
>
267 HashSet
<Key
>::Add(const Key
& key
)
271 Element
* element
= fTable
.Add(key
.GetHashCode());
279 template<typename Key
>
281 HashSet
<Key
>::Remove(const Key
& key
)
283 if (Element
* element
= _FindElement(key
)) {
284 fTable
.Remove(element
);
291 template<typename Key
>
293 HashSet
<Key
>::Clear()
299 template<typename Key
>
301 HashSet
<Key
>::Contains(const Key
& key
) const
303 return _FindElement(key
);
307 template<typename Key
>
309 HashSet
<Key
>::Size() const
311 return fTable
.CountElements();
315 template<typename Key
>
316 typename HashSet
<Key
>::Iterator
317 HashSet
<Key
>::GetIterator()
319 return Iterator(this);
323 template<typename Key
>
324 HashSetElement
<Key
> *
325 HashSet
<Key
>::_FindElement(const Key
& key
) const
327 Element
* element
= fTable
.FindFirst(key
.GetHashCode());
328 while (element
&& element
->fKey
!= key
) {
329 if (element
->fNext
>= 0)
330 element
= fTable
.ElementAt(element
->fNext
);
337 } // namespace BPrivate
339 using BPrivate::HashSet
;
340 using BPrivate::SynchronizedHashSet
;