1 // -*- mode: c++; c-basic-offset: 4 -*-
3 * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 #ifndef WTF_ListHashSet_h
23 #define WTF_ListHashSet_h
25 #include "Assertions.h"
31 // ListHashSet: Just like HashSet, this class provides a Set
32 // interface - a collection of unique objects with O(1) insertion,
33 // removal and test for containership. However, it also has an
34 // order - iterating it will always give back values in the order
35 // in which they are added.
37 // In theory it would be possible to add prepend, insertAfter, insertBefore,
38 // and an append that moves the element to the end even if already present,
39 // but unclear yet if these are needed.
41 template<typename Value
, typename HashFunctions
> class ListHashSet
;
43 template<typename T
> struct IdentityExtractor
;
45 template<typename Value
, typename HashFunctions
>
46 void deleteAllValues(const ListHashSet
<Value
, HashFunctions
>&);
48 template<typename ValueArg
, typename HashArg
> class ListHashSetIterator
;
49 template<typename ValueArg
, typename HashArg
> class ListHashSetConstIterator
;
51 template<typename ValueArg
> struct ListHashSetNode
;
52 template<typename ValueArg
> struct ListHashSetNodeAllocator
;
53 template<typename ValueArg
, typename HashArg
> struct ListHashSetNodeHashFunctions
;
55 template<typename ValueArg
, typename HashArg
= typename DefaultHash
<ValueArg
>::Hash
> class ListHashSet
{
57 typedef ListHashSetNode
<ValueArg
> Node
;
58 typedef ListHashSetNodeAllocator
<ValueArg
> NodeAllocator
;
60 typedef HashTraits
<Node
*> NodeTraits
;
61 typedef ListHashSetNodeHashFunctions
<ValueArg
, HashArg
> NodeHash
;
63 typedef HashTable
<Node
*, Node
*, IdentityExtractor
<Node
*>, NodeHash
, NodeTraits
, NodeTraits
> ImplType
;
65 typedef HashArg HashFunctions
;
68 typedef ValueArg ValueType
;
69 typedef ListHashSetIterator
<ValueType
, HashArg
> iterator
;
70 typedef ListHashSetConstIterator
<ValueType
, HashArg
> const_iterator
;
72 friend class ListHashSetConstIterator
<ValueType
, HashArg
>;
75 ListHashSet(const ListHashSet
&);
76 ListHashSet
& operator=(const ListHashSet
&);
79 void swap(ListHashSet
&);
87 const_iterator
begin() const;
88 const_iterator
end() const;
90 iterator
find(const ValueType
&);
91 const_iterator
find(const ValueType
&) const;
92 bool contains(const ValueType
&) const;
94 // the return value is a pair of an interator to the new value's location,
95 // and a bool that is true if an new entry was added
96 pair
<iterator
, bool> add(const ValueType
&);
98 void remove(const ValueType
&);
99 void remove(iterator
);
103 void unlinkAndDelete(Node
*);
104 void appendNode(Node
*);
105 void deleteAllNodes();
106 iterator
makeIterator(Node
*);
107 const_iterator
makeConstIterator(Node
*) const;
109 friend void deleteAllValues
<>(const ListHashSet
&);
114 OwnPtr
<NodeAllocator
> m_allocator
;
117 template<typename ValueArg
> struct ListHashSetNodeAllocator
{
118 typedef ListHashSetNode
<ValueArg
> Node
;
119 typedef ListHashSetNodeAllocator
<ValueArg
> NodeAllocator
;
121 ListHashSetNodeAllocator()
123 , m_isDoneWithInitialFreeList(false)
125 memset(m_pool
.pool
, 0, sizeof(m_pool
.pool
));
130 Node
* result
= m_freeList
;
133 return static_cast<Node
*>(fastMalloc(sizeof(Node
)));
135 ASSERT(!result
->m_isAllocated
);
137 Node
* next
= result
->m_next
;
138 ASSERT(!next
|| !next
->m_isAllocated
);
139 if (!next
&& !m_isDoneWithInitialFreeList
) {
141 if (next
== pastPool()) {
142 m_isDoneWithInitialFreeList
= true;
145 ASSERT(inPool(next
));
146 ASSERT(!next
->m_isAllocated
);
154 void deallocate(Node
* node
)
158 node
->m_isAllocated
= false;
160 node
->m_next
= m_freeList
;
169 Node
* pool() { return reinterpret_cast<Node
*>(m_pool
.pool
); }
170 Node
* pastPool() { return pool() + m_poolSize
; }
172 bool inPool(Node
* node
)
174 return node
>= pool() && node
< pastPool();
178 bool m_isDoneWithInitialFreeList
;
179 static const size_t m_poolSize
= 256;
181 char pool
[sizeof(Node
) * m_poolSize
];
186 template<typename ValueArg
> struct ListHashSetNode
{
187 typedef ListHashSetNodeAllocator
<ValueArg
> NodeAllocator
;
189 ListHashSetNode(ValueArg value
)
194 , m_isAllocated(true)
199 void* operator new(size_t, NodeAllocator
* allocator
)
201 return allocator
->allocate();
203 void destroy(NodeAllocator
* allocator
)
205 this->~ListHashSetNode();
206 allocator
->deallocate(this);
210 ListHashSetNode
* m_prev
;
211 ListHashSetNode
* m_next
;
218 template<typename ValueArg
, typename HashArg
> struct ListHashSetNodeHashFunctions
{
219 typedef ListHashSetNode
<ValueArg
> Node
;
221 static unsigned hash(Node
* const& key
) { return HashArg::hash(key
->m_value
); }
222 static bool equal(Node
* const& a
, Node
* const& b
) { return HashArg::equal(a
->m_value
, b
->m_value
); }
223 static const bool safeToCompareToEmptyOrDeleted
= false;
226 template<typename ValueArg
, typename HashArg
> class ListHashSetIterator
{
228 typedef ListHashSet
<ValueArg
, HashArg
> ListHashSetType
;
229 typedef ListHashSetIterator
<ValueArg
, HashArg
> iterator
;
230 typedef ListHashSetConstIterator
<ValueArg
, HashArg
> const_iterator
;
231 typedef ListHashSetNode
<ValueArg
> Node
;
232 typedef ValueArg ValueType
;
233 typedef ValueType
& ReferenceType
;
234 typedef ValueType
* PointerType
;
236 friend class ListHashSet
<ValueArg
, HashArg
>;
238 ListHashSetIterator(const ListHashSetType
* set
, Node
* position
) : m_iterator(set
, position
) { }
241 ListHashSetIterator() { }
243 // default copy, assignment and destructor are OK
245 PointerType
get() const { return const_cast<PointerType
>(m_iterator
.get()); }
246 ReferenceType
operator*() const { return *get(); }
247 PointerType
operator->() const { return get(); }
249 iterator
& operator++() { ++m_iterator
; return *this; }
251 // postfix ++ intentionally omitted
253 iterator
& operator--() { --m_iterator
; return *this; }
255 // postfix -- intentionally omitted
258 bool operator==(const iterator
& other
) const { return m_iterator
== other
.m_iterator
; }
259 bool operator!=(const iterator
& other
) const { return m_iterator
!= other
.m_iterator
; }
261 operator const_iterator() const { return m_iterator
; }
264 Node
* node() { return m_iterator
.node(); }
266 const_iterator m_iterator
;
269 template<typename ValueArg
, typename HashArg
> class ListHashSetConstIterator
{
271 typedef ListHashSet
<ValueArg
, HashArg
> ListHashSetType
;
272 typedef ListHashSetIterator
<ValueArg
, HashArg
> iterator
;
273 typedef ListHashSetConstIterator
<ValueArg
, HashArg
> const_iterator
;
274 typedef ListHashSetNode
<ValueArg
> Node
;
275 typedef ValueArg ValueType
;
276 typedef const ValueType
& ReferenceType
;
277 typedef const ValueType
* PointerType
;
279 friend class ListHashSet
<ValueArg
, HashArg
>;
280 friend class ListHashSetIterator
<ValueArg
, HashArg
>;
282 ListHashSetConstIterator(const ListHashSetType
* set
, Node
* position
)
284 , m_position(position
)
289 ListHashSetConstIterator()
293 PointerType
get() const
295 return &m_position
->m_value
;
297 ReferenceType
operator*() const { return *get(); }
298 PointerType
operator->() const { return get(); }
300 const_iterator
& operator++()
302 ASSERT(m_position
!= 0);
303 m_position
= m_position
->m_next
;
307 // postfix ++ intentionally omitted
309 const_iterator
& operator--()
311 ASSERT(m_position
!= m_set
->m_head
);
312 m_position
= m_position
->m_prev
;
316 // postfix -- intentionally omitted
319 bool operator==(const const_iterator
& other
) const
321 return m_position
== other
.m_position
;
323 bool operator!=(const const_iterator
& other
) const
325 return m_position
!= other
.m_position
;
329 Node
* node() { return m_position
; }
331 const ListHashSetType
* m_set
;
336 template<typename ValueType
, typename HashFunctions
>
337 struct ListHashSetTranslator
{
339 typedef ListHashSetNode
<ValueType
> Node
;
340 typedef ListHashSetNodeAllocator
<ValueType
> NodeAllocator
;
342 static unsigned hash(const ValueType
& key
) { return HashFunctions::hash(key
); }
343 static bool equal(Node
* const& a
, const ValueType
& b
) { return HashFunctions::equal(a
->m_value
, b
); }
344 static void translate(Node
*& location
, const ValueType
& key
, NodeAllocator
* allocator
)
346 location
= new (allocator
) Node(key
);
350 template<typename T
, typename U
>
351 inline ListHashSet
<T
, U
>::ListHashSet()
354 , m_allocator(new NodeAllocator
)
358 template<typename T
, typename U
>
359 inline ListHashSet
<T
, U
>::ListHashSet(const ListHashSet
& other
)
362 , m_allocator(new NodeAllocator
)
364 const_iterator end
= other
.end();
365 for (const_iterator it
= other
.begin(); it
!= end
; ++it
)
369 template<typename T
, typename U
>
370 inline ListHashSet
<T
, U
>& ListHashSet
<T
, U
>::operator=(const ListHashSet
& other
)
372 ListHashSet
tmp(other
);
377 template<typename T
, typename U
>
378 inline void ListHashSet
<T
, U
>::swap(ListHashSet
& other
)
380 m_impl
.swap(other
.m_impl
);
381 std::swap(m_head
, other
.m_head
);
382 std::swap(m_tail
, other
.m_tail
);
383 m_allocator
.swap(other
.m_allocator
);
387 template<typename T
, typename U
>
388 inline ListHashSet
<T
, U
>::~ListHashSet()
393 template<typename T
, typename U
>
394 inline int ListHashSet
<T
, U
>::size() const
396 return m_impl
.size();
399 template<typename T
, typename U
>
400 inline int ListHashSet
<T
, U
>::capacity() const
402 return m_impl
.capacity();
405 template<typename T
, typename U
>
406 inline bool ListHashSet
<T
, U
>::isEmpty() const
408 return m_impl
.isEmpty();
411 template<typename T
, typename U
>
412 inline typename ListHashSet
<T
, U
>::iterator ListHashSet
<T
, U
>::begin()
414 return makeIterator(m_head
);
417 template<typename T
, typename U
>
418 inline typename ListHashSet
<T
, U
>::iterator ListHashSet
<T
, U
>::end()
420 return makeIterator(0);
423 template<typename T
, typename U
>
424 inline typename ListHashSet
<T
, U
>::const_iterator ListHashSet
<T
, U
>::begin() const
426 return makeConstIterator(m_head
);
429 template<typename T
, typename U
>
430 inline typename ListHashSet
<T
, U
>::const_iterator ListHashSet
<T
, U
>::end() const
432 return makeConstIterator(0);
435 template<typename T
, typename U
>
436 inline typename ListHashSet
<T
, U
>::iterator ListHashSet
<T
, U
>::find(const ValueType
& value
)
438 typedef ListHashSetTranslator
<ValueType
, HashFunctions
> Translator
;
439 typename
ImplType::iterator it
= m_impl
.template find
<ValueType
, Translator
>(value
);
440 if (it
== m_impl
.end())
442 return makeIterator(*it
);
445 template<typename T
, typename U
>
446 inline typename ListHashSet
<T
, U
>::const_iterator ListHashSet
<T
, U
>::find(const ValueType
& value
) const
448 typedef ListHashSetTranslator
<ValueType
, HashFunctions
> Translator
;
449 typename
ImplType::const_iterator it
= m_impl
.template find
<ValueType
, Translator
>(value
);
450 if (it
== m_impl
.end())
452 return makeConstIterator(*it
);
455 template<typename T
, typename U
>
456 inline bool ListHashSet
<T
, U
>::contains(const ValueType
& value
) const
458 typedef ListHashSetTranslator
<ValueType
, HashFunctions
> Translator
;
459 return m_impl
.template contains
<ValueType
, Translator
>(value
);
462 template<typename T
, typename U
>
463 pair
<typename ListHashSet
<T
, U
>::iterator
, bool> ListHashSet
<T
, U
>::add(const ValueType
&value
)
465 typedef ListHashSetTranslator
<ValueType
, HashFunctions
> Translator
;
466 pair
<typename
ImplType::iterator
, bool> result
= m_impl
.template add
<ValueType
, NodeAllocator
*, Translator
>(value
, m_allocator
.get());
468 appendNode(*result
.first
);
469 return std::make_pair(makeIterator(*result
.first
), result
.second
);
472 template<typename T
, typename U
>
473 inline void ListHashSet
<T
, U
>::remove(iterator it
)
477 m_impl
.remove(it
.node());
478 unlinkAndDelete(it
.node());
481 template<typename T
, typename U
>
482 inline void ListHashSet
<T
, U
>::remove(const ValueType
& value
)
487 template<typename T
, typename U
>
488 inline void ListHashSet
<T
, U
>::clear()
496 template<typename T
, typename U
>
497 void ListHashSet
<T
, U
>::unlinkAndDelete(Node
* node
)
500 ASSERT(node
== m_head
);
501 m_head
= node
->m_next
;
503 ASSERT(node
!= m_head
);
504 node
->m_prev
->m_next
= node
->m_next
;
508 ASSERT(node
== m_tail
);
509 m_tail
= node
->m_prev
;
511 ASSERT(node
!= m_tail
);
512 node
->m_next
->m_prev
= node
->m_prev
;
515 node
->destroy(m_allocator
.get());
518 template<typename T
, typename U
>
519 void ListHashSet
<T
, U
>::appendNode(Node
* node
)
521 node
->m_prev
= m_tail
;
526 m_tail
->m_next
= node
;
535 template<typename T
, typename U
>
536 void ListHashSet
<T
, U
>::deleteAllNodes()
541 for (Node
* node
= m_head
, *next
= m_head
->m_next
; node
; node
= next
, next
= node
? node
->m_next
: 0)
542 node
->destroy(m_allocator
.get());
545 template<typename T
, typename U
>
546 inline ListHashSetIterator
<T
, U
> ListHashSet
<T
, U
>::makeIterator(Node
* position
)
548 return ListHashSetIterator
<T
, U
>(this, position
);
551 template<typename T
, typename U
>
552 inline ListHashSetConstIterator
<T
, U
> ListHashSet
<T
, U
>::makeConstIterator(Node
* position
) const
554 return ListHashSetConstIterator
<T
, U
>(this, position
);
557 template<bool, typename ValueType
, typename HashTableType
>
558 void deleteAllValues(HashTableType
& collection
)
560 typedef typename
HashTableType::const_iterator iterator
;
561 iterator end
= collection
.end();
562 for (iterator it
= collection
.begin(); it
!= end
; ++it
)
563 delete (*it
)->m_value
;
566 template<typename T
, typename U
>
567 inline void deleteAllValues(const ListHashSet
<T
, U
>& collection
)
569 deleteAllValues
<true, typename ListHashSet
<T
, U
>::ValueType
>(collection
.m_impl
);
574 using WTF::ListHashSet
;
576 #endif /* WTF_ListHashSet_h */