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

Side by Side Diff: third_party/WebKit/Source/wtf/ListHashSet.h

Issue 1611343002: wtf reformat test Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: pydent Created 4 years, 11 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserv ed. 2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserv ed.
3 * Copyright (C) 2011, Benjamin Poulain <ikipou@gmail.com> 3 * Copyright (C) 2011, Benjamin Poulain <ikipou@gmail.com>
4 * 4 *
5 * This library is free software; you can redistribute it and/or 5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public 6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either 7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version. 8 * version 2 of the License, or (at your option) any later version.
9 * 9 *
10 * This library is distributed in the hope that it will be useful, 10 * This library is distributed in the hope that it will be useful,
(...skipping 20 matching lines...) Expand all
31 31
32 // ListHashSet: Just like HashSet, this class provides a Set interface - a 32 // ListHashSet: Just like HashSet, this class provides a Set interface - a
33 // collection of unique objects with O(1) insertion, removal and test for 33 // collection of unique objects with O(1) insertion, removal and test for
34 // containership. However, it also has an order - iterating it will always give 34 // containership. However, it also has an order - iterating it will always give
35 // back values in the order in which they are added. 35 // back values in the order in which they are added.
36 36
37 // Unlike iteration of most WTF Hash data structures, iteration is guaranteed 37 // Unlike iteration of most WTF Hash data structures, iteration is guaranteed
38 // safe against mutation of the ListHashSet, except for removal of the item 38 // safe against mutation of the ListHashSet, except for removal of the item
39 // currently pointed to by a given iterator. 39 // currently pointed to by a given iterator.
40 40
41 template <typename Value, size_t inlineCapacity, typename HashFunctions, typenam e Allocator> class ListHashSet; 41 template <typename Value,
42 42 size_t inlineCapacity,
43 template <typename Set> class ListHashSetIterator; 43 typename HashFunctions,
44 template <typename Set> class ListHashSetConstIterator; 44 typename Allocator>
45 template <typename Set> class ListHashSetReverseIterator; 45 class ListHashSet;
46 template <typename Set> class ListHashSetConstReverseIterator; 46
47 47 template <typename Set>
48 template <typename ValueArg> class ListHashSetNodeBase; 48 class ListHashSetIterator;
49 template <typename ValueArg, typename Allocator> class ListHashSetNode; 49 template <typename Set>
50 template <typename ValueArg, size_t inlineCapacity> struct ListHashSetAllocator; 50 class ListHashSetConstIterator;
51 51 template <typename Set>
52 template <typename HashArg> struct ListHashSetNodeHashFunctions; 52 class ListHashSetReverseIterator;
53 template <typename HashArg> struct ListHashSetTranslator; 53 template <typename Set>
54 class ListHashSetConstReverseIterator;
55
56 template <typename ValueArg>
57 class ListHashSetNodeBase;
58 template <typename ValueArg, typename Allocator>
59 class ListHashSetNode;
60 template <typename ValueArg, size_t inlineCapacity>
61 struct ListHashSetAllocator;
62
63 template <typename HashArg>
64 struct ListHashSetNodeHashFunctions;
65 template <typename HashArg>
66 struct ListHashSetTranslator;
54 67
55 // Note that for a ListHashSet you cannot specify the HashTraits as a template 68 // Note that for a ListHashSet you cannot specify the HashTraits as a template
56 // argument. It uses the default hash traits for the ValueArg type. 69 // argument. It uses the default hash traits for the ValueArg type.
57 template <typename ValueArg, size_t inlineCapacity = 256, typename HashArg = typ ename DefaultHash<ValueArg>::Hash, typename AllocatorArg = ListHashSetAllocator< ValueArg, inlineCapacity>> 70 template <typename ValueArg,
58 class ListHashSet : public ConditionalDestructor<ListHashSet<ValueArg, inlineCap acity, HashArg, AllocatorArg>, AllocatorArg::isGarbageCollected> { 71 size_t inlineCapacity = 256,
59 typedef AllocatorArg Allocator; 72 typename HashArg = typename DefaultHash<ValueArg>::Hash,
60 WTF_USE_ALLOCATOR(ListHashSet, Allocator); 73 typename AllocatorArg =
61 74 ListHashSetAllocator<ValueArg, inlineCapacity>>
62 typedef ListHashSetNode<ValueArg, Allocator> Node; 75 class ListHashSet
63 typedef HashTraits<Node*> NodeTraits; 76 : public ConditionalDestructor<
64 typedef ListHashSetNodeHashFunctions<HashArg> NodeHash; 77 ListHashSet<ValueArg, inlineCapacity, HashArg, AllocatorArg>,
65 typedef ListHashSetTranslator<HashArg> BaseTranslator; 78 AllocatorArg::isGarbageCollected> {
66 79 typedef AllocatorArg Allocator;
67 typedef HashTable<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, Nod eTraits, typename Allocator::TableAllocator> ImplType; 80 WTF_USE_ALLOCATOR(ListHashSet, Allocator);
68 typedef HashTableIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTra its, NodeTraits, typename Allocator::TableAllocator> ImplTypeIterator; 81
69 typedef HashTableConstIterator<Node*, Node*, IdentityExtractor, NodeHash, No deTraits, NodeTraits, typename Allocator::TableAllocator> ImplTypeConstIterator; 82 typedef ListHashSetNode<ValueArg, Allocator> Node;
70 83 typedef HashTraits<Node*> NodeTraits;
71 typedef HashArg HashFunctions; 84 typedef ListHashSetNodeHashFunctions<HashArg> NodeHash;
72 85 typedef ListHashSetTranslator<HashArg> BaseTranslator;
73 public: 86
74 typedef ValueArg ValueType; 87 typedef HashTable<Node*,
75 typedef HashTraits<ValueType> ValueTraits; 88 Node*,
76 typedef typename ValueTraits::PeekInType ValuePeekInType; 89 IdentityExtractor,
77 typedef typename ValueTraits::PassInType ValuePassInType; 90 NodeHash,
78 typedef typename ValueTraits::PassOutType ValuePassOutType; 91 NodeTraits,
79 92 NodeTraits,
80 typedef ListHashSetIterator<ListHashSet> iterator; 93 typename Allocator::TableAllocator>
81 typedef ListHashSetConstIterator<ListHashSet> const_iterator; 94 ImplType;
82 friend class ListHashSetIterator<ListHashSet>; 95 typedef HashTableIterator<Node*,
83 friend class ListHashSetConstIterator<ListHashSet>; 96 Node*,
84 97 IdentityExtractor,
85 typedef ListHashSetReverseIterator<ListHashSet> reverse_iterator; 98 NodeHash,
86 typedef ListHashSetConstReverseIterator<ListHashSet> const_reverse_iterator; 99 NodeTraits,
87 friend class ListHashSetReverseIterator<ListHashSet>; 100 NodeTraits,
88 friend class ListHashSetConstReverseIterator<ListHashSet>; 101 typename Allocator::TableAllocator>
89 102 ImplTypeIterator;
90 template <typename ValueType> struct HashTableAddResult final { 103 typedef HashTableConstIterator<Node*,
91 STACK_ALLOCATED(); 104 Node*,
92 HashTableAddResult(Node* storedValue, bool isNewEntry) : storedValue(sto redValue), isNewEntry(isNewEntry) { } 105 IdentityExtractor,
93 Node* storedValue; 106 NodeHash,
94 bool isNewEntry; 107 NodeTraits,
95 }; 108 NodeTraits,
96 typedef HashTableAddResult<ValueType> AddResult; 109 typename Allocator::TableAllocator>
97 110 ImplTypeConstIterator;
98 ListHashSet(); 111
99 ListHashSet(const ListHashSet&); 112 typedef HashArg HashFunctions;
100 ListHashSet& operator=(const ListHashSet&); 113
101 void finalize(); 114 public:
102 115 typedef ValueArg ValueType;
103 void swap(ListHashSet&); 116 typedef HashTraits<ValueType> ValueTraits;
104 117 typedef typename ValueTraits::PeekInType ValuePeekInType;
105 unsigned size() const { return m_impl.size(); } 118 typedef typename ValueTraits::PassInType ValuePassInType;
106 unsigned capacity() const { return m_impl.capacity(); } 119 typedef typename ValueTraits::PassOutType ValuePassOutType;
107 bool isEmpty() const { return m_impl.isEmpty(); } 120
108 121 typedef ListHashSetIterator<ListHashSet> iterator;
109 iterator begin() { return makeIterator(m_head); } 122 typedef ListHashSetConstIterator<ListHashSet> const_iterator;
110 iterator end() { return makeIterator(0); } 123 friend class ListHashSetIterator<ListHashSet>;
111 const_iterator begin() const { return makeConstIterator(m_head); } 124 friend class ListHashSetConstIterator<ListHashSet>;
112 const_iterator end() const { return makeConstIterator(0); } 125
113 126 typedef ListHashSetReverseIterator<ListHashSet> reverse_iterator;
114 reverse_iterator rbegin() { return makeReverseIterator(m_tail); } 127 typedef ListHashSetConstReverseIterator<ListHashSet> const_reverse_iterator;
115 reverse_iterator rend() { return makeReverseIterator(0); } 128 friend class ListHashSetReverseIterator<ListHashSet>;
116 const_reverse_iterator rbegin() const { return makeConstReverseIterator(m_ta il); } 129 friend class ListHashSetConstReverseIterator<ListHashSet>;
117 const_reverse_iterator rend() const { return makeConstReverseIterator(0); } 130
118 131 template <typename ValueType>
119 ValueType& first(); 132 struct HashTableAddResult final {
120 const ValueType& first() const; 133 STACK_ALLOCATED();
121 void removeFirst(); 134 HashTableAddResult(Node* storedValue, bool isNewEntry)
122 135 : storedValue(storedValue), isNewEntry(isNewEntry) {}
123 ValueType& last(); 136 Node* storedValue;
124 const ValueType& last() const; 137 bool isNewEntry;
125 void removeLast(); 138 };
126 139 typedef HashTableAddResult<ValueType> AddResult;
127 iterator find(ValuePeekInType); 140
128 const_iterator find(ValuePeekInType) const; 141 ListHashSet();
129 bool contains(ValuePeekInType) const; 142 ListHashSet(const ListHashSet&);
130 143 ListHashSet& operator=(const ListHashSet&);
131 // An alternate version of find() that finds the object by hashing and 144 void finalize();
132 // comparing with some other type, to avoid the cost of type conversion. 145
133 // The HashTranslator interface is defined in HashSet. 146 void swap(ListHashSet&);
134 template <typename HashTranslator, typename T> iterator find(const T&); 147
135 template <typename HashTranslator, typename T> const_iterator find(const T&) const; 148 unsigned size() const { return m_impl.size(); }
136 template <typename HashTranslator, typename T> bool contains(const T&) const ; 149 unsigned capacity() const { return m_impl.capacity(); }
137 150 bool isEmpty() const { return m_impl.isEmpty(); }
138 // The return value of add is a pair of a pointer to the stored value, and a 151
139 // bool that is true if an new entry was added. 152 iterator begin() { return makeIterator(m_head); }
140 AddResult add(ValuePassInType); 153 iterator end() { return makeIterator(0); }
141 154 const_iterator begin() const { return makeConstIterator(m_head); }
142 // Same as add() except that the return value is an iterator. Useful in 155 const_iterator end() const { return makeConstIterator(0); }
143 // cases where it's needed to have the same return value as find() and where 156
144 // it's not possible to use a pointer to the storedValue. 157 reverse_iterator rbegin() { return makeReverseIterator(m_tail); }
145 iterator addReturnIterator(ValuePassInType); 158 reverse_iterator rend() { return makeReverseIterator(0); }
146 159 const_reverse_iterator rbegin() const {
147 // Add the value to the end of the collection. If the value was already in 160 return makeConstReverseIterator(m_tail);
148 // the list, it is moved to the end. 161 }
149 AddResult appendOrMoveToLast(ValuePassInType); 162 const_reverse_iterator rend() const { return makeConstReverseIterator(0); }
150 163
151 // Add the value to the beginning of the collection. If the value was 164 ValueType& first();
152 // already in the list, it is moved to the beginning. 165 const ValueType& first() const;
153 AddResult prependOrMoveToFirst(ValuePassInType); 166 void removeFirst();
154 167
155 AddResult insertBefore(ValuePeekInType beforeValue, ValuePassInType newValue ); 168 ValueType& last();
156 AddResult insertBefore(iterator, ValuePassInType); 169 const ValueType& last() const;
157 170 void removeLast();
158 void remove(ValuePeekInType value) { return remove(find(value)); } 171
159 void remove(iterator); 172 iterator find(ValuePeekInType);
160 void clear(); 173 const_iterator find(ValuePeekInType) const;
161 template <typename Collection> 174 bool contains(ValuePeekInType) const;
162 void removeAll(const Collection& other) { WTF::removeAll(*this, other); } 175
163 176 // An alternate version of find() that finds the object by hashing and
164 ValuePassOutType take(iterator); 177 // comparing with some other type, to avoid the cost of type conversion.
165 ValuePassOutType take(ValuePeekInType); 178 // The HashTranslator interface is defined in HashSet.
166 ValuePassOutType takeFirst(); 179 template <typename HashTranslator, typename T>
167 180 iterator find(const T&);
168 template <typename VisitorDispatcher> 181 template <typename HashTranslator, typename T>
169 void trace(VisitorDispatcher); 182 const_iterator find(const T&) const;
170 183 template <typename HashTranslator, typename T>
171 private: 184 bool contains(const T&) const;
172 void unlink(Node*); 185
173 void unlinkAndDelete(Node*); 186 // The return value of add is a pair of a pointer to the stored value, and a
174 void appendNode(Node*); 187 // bool that is true if an new entry was added.
175 void prependNode(Node*); 188 AddResult add(ValuePassInType);
176 void insertNodeBefore(Node* beforeNode, Node* newNode); 189
177 void deleteAllNodes(); 190 // Same as add() except that the return value is an iterator. Useful in
178 Allocator* allocator() const { return m_allocatorProvider.get(); } 191 // cases where it's needed to have the same return value as find() and where
179 void createAllocatorIfNeeded() { m_allocatorProvider.createAllocatorIfNeeded (); } 192 // it's not possible to use a pointer to the storedValue.
180 void deallocate(Node* node) const { m_allocatorProvider.deallocate(node); } 193 iterator addReturnIterator(ValuePassInType);
181 194
182 iterator makeIterator(Node* position) { return iterator(this, position); } 195 // Add the value to the end of the collection. If the value was already in
183 const_iterator makeConstIterator(Node* position) const { return const_iterat or(this, position); } 196 // the list, it is moved to the end.
184 reverse_iterator makeReverseIterator(Node* position) { return reverse_iterat or(this, position); } 197 AddResult appendOrMoveToLast(ValuePassInType);
185 const_reverse_iterator makeConstReverseIterator(Node* position) const { retu rn const_reverse_iterator(this, position); } 198
186 199 // Add the value to the beginning of the collection. If the value was
187 ImplType m_impl; 200 // already in the list, it is moved to the beginning.
188 Node* m_head; 201 AddResult prependOrMoveToFirst(ValuePassInType);
189 Node* m_tail; 202
190 typename Allocator::AllocatorProvider m_allocatorProvider; 203 AddResult insertBefore(ValuePeekInType beforeValue, ValuePassInType newValue);
204 AddResult insertBefore(iterator, ValuePassInType);
205
206 void remove(ValuePeekInType value) { return remove(find(value)); }
207 void remove(iterator);
208 void clear();
209 template <typename Collection>
210 void removeAll(const Collection& other) {
211 WTF::removeAll(*this, other);
212 }
213
214 ValuePassOutType take(iterator);
215 ValuePassOutType take(ValuePeekInType);
216 ValuePassOutType takeFirst();
217
218 template <typename VisitorDispatcher>
219 void trace(VisitorDispatcher);
220
221 private:
222 void unlink(Node*);
223 void unlinkAndDelete(Node*);
224 void appendNode(Node*);
225 void prependNode(Node*);
226 void insertNodeBefore(Node* beforeNode, Node* newNode);
227 void deleteAllNodes();
228 Allocator* allocator() const { return m_allocatorProvider.get(); }
229 void createAllocatorIfNeeded() {
230 m_allocatorProvider.createAllocatorIfNeeded();
231 }
232 void deallocate(Node* node) const { m_allocatorProvider.deallocate(node); }
233
234 iterator makeIterator(Node* position) { return iterator(this, position); }
235 const_iterator makeConstIterator(Node* position) const {
236 return const_iterator(this, position);
237 }
238 reverse_iterator makeReverseIterator(Node* position) {
239 return reverse_iterator(this, position);
240 }
241 const_reverse_iterator makeConstReverseIterator(Node* position) const {
242 return const_reverse_iterator(this, position);
243 }
244
245 ImplType m_impl;
246 Node* m_head;
247 Node* m_tail;
248 typename Allocator::AllocatorProvider m_allocatorProvider;
191 }; 249 };
192 250
193 // ListHashSetNode has this base class to hold the members because the MSVC 251 // ListHashSetNode has this base class to hold the members because the MSVC
194 // compiler otherwise gets into circular template dependencies when trying to do 252 // compiler otherwise gets into circular template dependencies when trying to do
195 // sizeof on a node. 253 // sizeof on a node.
196 template <typename ValueArg> class ListHashSetNodeBase { 254 template <typename ValueArg>
197 DISALLOW_NEW(); 255 class ListHashSetNodeBase {
198 protected: 256 DISALLOW_NEW();
199 ListHashSetNodeBase(const ValueArg& value) 257
200 : m_value(value) 258 protected:
201 , m_prev(nullptr) 259 ListHashSetNodeBase(const ValueArg& value)
202 , m_next(nullptr) 260 : m_value(value),
261 m_prev(nullptr),
262 m_next(nullptr)
203 #if ENABLE(ASSERT) 263 #if ENABLE(ASSERT)
204 , m_isAllocated(true) 264 ,
265 m_isAllocated(true)
205 #endif 266 #endif
206 { 267 {
207 } 268 }
208 269
209 template <typename U> 270 template <typename U>
210 ListHashSetNodeBase(const U& value) 271 ListHashSetNodeBase(const U& value)
211 : m_value(value) 272 : m_value(value),
212 , m_prev(nullptr) 273 m_prev(nullptr),
213 , m_next(nullptr) 274 m_next(nullptr)
214 #if ENABLE(ASSERT) 275 #if ENABLE(ASSERT)
215 , m_isAllocated(true) 276 ,
277 m_isAllocated(true)
216 #endif 278 #endif
217 { 279 {
218 } 280 }
219 281
220 public: 282 public:
221 ValueArg m_value; 283 ValueArg m_value;
222 ListHashSetNodeBase* m_prev; 284 ListHashSetNodeBase* m_prev;
223 ListHashSetNodeBase* m_next; 285 ListHashSetNodeBase* m_next;
224 #if ENABLE(ASSERT) 286 #if ENABLE(ASSERT)
225 bool m_isAllocated; 287 bool m_isAllocated;
226 #endif 288 #endif
227 }; 289 };
228 290
229 // This allocator is only used for non-Heap ListHashSets. 291 // This allocator is only used for non-Heap ListHashSets.
230 template <typename ValueArg, size_t inlineCapacity> 292 template <typename ValueArg, size_t inlineCapacity>
231 struct ListHashSetAllocator : public PartitionAllocator { 293 struct ListHashSetAllocator : public PartitionAllocator {
232 typedef PartitionAllocator TableAllocator; 294 typedef PartitionAllocator TableAllocator;
233 typedef ListHashSetNode<ValueArg, ListHashSetAllocator> Node; 295 typedef ListHashSetNode<ValueArg, ListHashSetAllocator> Node;
234 typedef ListHashSetNodeBase<ValueArg> NodeBase; 296 typedef ListHashSetNodeBase<ValueArg> NodeBase;
235 297
236 class AllocatorProvider { 298 class AllocatorProvider {
237 DISALLOW_NEW(); 299 DISALLOW_NEW();
238 public: 300
239 AllocatorProvider() : m_allocator(nullptr) {} 301 public:
240 void createAllocatorIfNeeded() 302 AllocatorProvider() : m_allocator(nullptr) {}
241 { 303 void createAllocatorIfNeeded() {
242 if (!m_allocator) 304 if (!m_allocator)
243 m_allocator = new ListHashSetAllocator; 305 m_allocator = new ListHashSetAllocator;
244 }
245
246 void releaseAllocator()
247 {
248 delete m_allocator;
249 m_allocator = nullptr;
250 }
251
252 void swap(AllocatorProvider& other)
253 {
254 std::swap(m_allocator, other.m_allocator);
255 }
256
257 void deallocate(Node* node) const
258 {
259 ASSERT(m_allocator);
260 m_allocator->deallocate(node);
261 }
262
263 ListHashSetAllocator* get() const
264 {
265 ASSERT(m_allocator);
266 return m_allocator;
267 }
268
269 private:
270 // Not using OwnPtr as this pointer should be deleted at
271 // releaseAllocator() method rather than at destructor.
272 ListHashSetAllocator* m_allocator;
273 };
274
275 ListHashSetAllocator()
276 : m_freeList(pool())
277 , m_isDoneWithInitialFreeList(false)
278 {
279 memset(m_pool.buffer, 0, sizeof(m_pool.buffer));
280 } 306 }
281 307
282 Node* allocateNode() 308 void releaseAllocator() {
283 { 309 delete m_allocator;
284 Node* result = m_freeList; 310 m_allocator = nullptr;
285
286 if (!result)
287 return static_cast<Node*>(WTF::Partitions::fastMalloc(sizeof(NodeBas e), WTF_HEAP_PROFILER_TYPE_NAME(Node)));
288
289 ASSERT(!result->m_isAllocated);
290
291 Node* next = result->next();
292 ASSERT(!next || !next->m_isAllocated);
293 if (!next && !m_isDoneWithInitialFreeList) {
294 next = result + 1;
295 if (next == pastPool()) {
296 m_isDoneWithInitialFreeList = true;
297 next = nullptr;
298 } else {
299 ASSERT(inPool(next));
300 ASSERT(!next->m_isAllocated);
301 }
302 }
303 m_freeList = next;
304
305 return result;
306 } 311 }
307 312
308 void deallocate(Node* node) 313 void swap(AllocatorProvider& other) {
309 { 314 std::swap(m_allocator, other.m_allocator);
310 if (inPool(node)) { 315 }
316
317 void deallocate(Node* node) const {
318 ASSERT(m_allocator);
319 m_allocator->deallocate(node);
320 }
321
322 ListHashSetAllocator* get() const {
323 ASSERT(m_allocator);
324 return m_allocator;
325 }
326
327 private:
328 // Not using OwnPtr as this pointer should be deleted at
329 // releaseAllocator() method rather than at destructor.
330 ListHashSetAllocator* m_allocator;
331 };
332
333 ListHashSetAllocator()
334 : m_freeList(pool()), m_isDoneWithInitialFreeList(false) {
335 memset(m_pool.buffer, 0, sizeof(m_pool.buffer));
336 }
337
338 Node* allocateNode() {
339 Node* result = m_freeList;
340
341 if (!result)
342 return static_cast<Node*>(WTF::Partitions::fastMalloc(
343 sizeof(NodeBase), WTF_HEAP_PROFILER_TYPE_NAME(Node)));
344
345 ASSERT(!result->m_isAllocated);
346
347 Node* next = result->next();
348 ASSERT(!next || !next->m_isAllocated);
349 if (!next && !m_isDoneWithInitialFreeList) {
350 next = result + 1;
351 if (next == pastPool()) {
352 m_isDoneWithInitialFreeList = true;
353 next = nullptr;
354 } else {
355 ASSERT(inPool(next));
356 ASSERT(!next->m_isAllocated);
357 }
358 }
359 m_freeList = next;
360
361 return result;
362 }
363
364 void deallocate(Node* node) {
365 if (inPool(node)) {
311 #if ENABLE(ASSERT) 366 #if ENABLE(ASSERT)
312 node->m_isAllocated = false; 367 node->m_isAllocated = false;
313 #endif 368 #endif
314 node->m_next = m_freeList; 369 node->m_next = m_freeList;
315 m_freeList = node; 370 m_freeList = node;
316 return; 371 return;
317 }
318
319 WTF::Partitions::fastFree(node);
320 } 372 }
321 373
322 bool inPool(Node* node) 374 WTF::Partitions::fastFree(node);
323 { 375 }
324 return node >= pool() && node < pastPool(); 376
325 } 377 bool inPool(Node* node) { return node >= pool() && node < pastPool(); }
326 378
327 static void traceValue(typename PartitionAllocator::Visitor* visitor, Node* node) {} 379 static void traceValue(typename PartitionAllocator::Visitor* visitor,
328 380 Node* node) {}
329 private: 381
330 Node* pool() { return reinterpret_cast_ptr<Node*>(m_pool.buffer); } 382 private:
331 Node* pastPool() { return pool() + m_poolSize; } 383 Node* pool() { return reinterpret_cast_ptr<Node*>(m_pool.buffer); }
332 384 Node* pastPool() { return pool() + m_poolSize; }
333 Node* m_freeList; 385
334 bool m_isDoneWithInitialFreeList; 386 Node* m_freeList;
387 bool m_isDoneWithInitialFreeList;
335 #if defined(MEMORY_SANITIZER_INITIAL_SIZE) 388 #if defined(MEMORY_SANITIZER_INITIAL_SIZE)
336 // The allocation pool for nodes is one big chunk that ASAN has no insight 389 // The allocation pool for nodes is one big chunk that ASAN has no insight
337 // into, so it can cloak errors. Make it as small as possible to force nodes 390 // into, so it can cloak errors. Make it as small as possible to force nodes
338 // to be allocated individually where ASAN can see them. 391 // to be allocated individually where ASAN can see them.
339 static const size_t m_poolSize = 1; 392 static const size_t m_poolSize = 1;
340 #else 393 #else
341 static const size_t m_poolSize = inlineCapacity; 394 static const size_t m_poolSize = inlineCapacity;
342 #endif 395 #endif
343 AlignedBuffer<sizeof(NodeBase) * m_poolSize, WTF_ALIGN_OF(NodeBase)> m_pool; 396 AlignedBuffer<sizeof(NodeBase) * m_poolSize, WTF_ALIGN_OF(NodeBase)> m_pool;
344 }; 397 };
345 398
346 template <typename ValueArg, typename AllocatorArg> class ListHashSetNode : publ ic ListHashSetNodeBase<ValueArg> { 399 template <typename ValueArg, typename AllocatorArg>
347 public: 400 class ListHashSetNode : public ListHashSetNodeBase<ValueArg> {
348 typedef AllocatorArg NodeAllocator; 401 public:
349 typedef ValueArg Value; 402 typedef AllocatorArg NodeAllocator;
350 403 typedef ValueArg Value;
351 template <typename U> 404
352 ListHashSetNode(U value) 405 template <typename U>
353 : ListHashSetNodeBase<ValueArg>(value) {} 406 ListHashSetNode(U value) : ListHashSetNodeBase<ValueArg>(value) {}
354 407
355 void* operator new(size_t, NodeAllocator* allocator) 408 void* operator new(size_t, NodeAllocator* allocator) {
356 { 409 static_assert(
357 static_assert(sizeof(ListHashSetNode) == sizeof(ListHashSetNodeBase<Valu eArg>), "please add any fields to the base"); 410 sizeof(ListHashSetNode) == sizeof(ListHashSetNodeBase<ValueArg>),
358 return allocator->allocateNode(); 411 "please add any fields to the base");
359 } 412 return allocator->allocateNode();
360 413 }
361 void setWasAlreadyDestructed() 414
362 { 415 void setWasAlreadyDestructed() {
363 if (NodeAllocator::isGarbageCollected && !IsTriviallyDestructible<ValueA rg>::value) 416 if (NodeAllocator::isGarbageCollected &&
364 this->m_prev = unlinkedNodePointer(); 417 !IsTriviallyDestructible<ValueArg>::value)
365 } 418 this->m_prev = unlinkedNodePointer();
366 419 }
367 bool wasAlreadyDestructed() const 420
368 { 421 bool wasAlreadyDestructed() const {
369 ASSERT(NodeAllocator::isGarbageCollected); 422 ASSERT(NodeAllocator::isGarbageCollected);
370 return this->m_prev == unlinkedNodePointer(); 423 return this->m_prev == unlinkedNodePointer();
371 } 424 }
372 425
373 static void finalize(void* pointer) 426 static void finalize(void* pointer) {
374 { 427 ASSERT(
375 ASSERT(!IsTriviallyDestructible<ValueArg>::value); // No need to waste t ime calling finalize if it's not needed. 428 !IsTriviallyDestructible<ValueArg>::
376 ListHashSetNode* self = reinterpret_cast_ptr<ListHashSetNode*>(pointer); 429 value); // No need to waste time calling finalize if it's not neede d.
377 430 ListHashSetNode* self = reinterpret_cast_ptr<ListHashSetNode*>(pointer);
378 // Check whether this node was already destructed before being unlinked 431
379 // from the collection. 432 // Check whether this node was already destructed before being unlinked
380 if (self->wasAlreadyDestructed()) 433 // from the collection.
381 return; 434 if (self->wasAlreadyDestructed())
382 435 return;
383 self->m_value.~ValueArg(); 436
384 } 437 self->m_value.~ValueArg();
385 void finalizeGarbageCollectedObject() 438 }
386 { 439 void finalizeGarbageCollectedObject() { finalize(this); }
387 finalize(this); 440
388 } 441 void destroy(NodeAllocator* allocator) {
389 442 this->~ListHashSetNode();
390 void destroy(NodeAllocator* allocator) 443 setWasAlreadyDestructed();
391 { 444 allocator->deallocate(this);
392 this->~ListHashSetNode(); 445 }
393 setWasAlreadyDestructed(); 446
394 allocator->deallocate(this); 447 // This is not called in normal tracing, but it is called if we find a
395 } 448 // pointer to a node on the stack using conservative scanning. Since the
396 449 // original ListHashSet may no longer exist we make sure to mark the
397 // This is not called in normal tracing, but it is called if we find a 450 // neighbours in the chain too.
398 // pointer to a node on the stack using conservative scanning. Since the 451 template <typename VisitorDispatcher>
399 // original ListHashSet may no longer exist we make sure to mark the 452 void trace(VisitorDispatcher visitor) {
400 // neighbours in the chain too. 453 // The conservative stack scan can find nodes that have been removed
401 template <typename VisitorDispatcher> 454 // from the set and destructed. We don't need to trace these, and it
402 void trace(VisitorDispatcher visitor) 455 // would be wrong to do so, because the class will not expect the trace
403 { 456 // method to be called after the destructor. It's an error to remove a
404 // The conservative stack scan can find nodes that have been removed 457 // node from the ListHashSet while an iterator is positioned at that
405 // from the set and destructed. We don't need to trace these, and it 458 // node, so there should be no valid pointers from the stack to a
406 // would be wrong to do so, because the class will not expect the trace 459 // destructed node.
407 // method to be called after the destructor. It's an error to remove a 460 if (wasAlreadyDestructed())
408 // node from the ListHashSet while an iterator is positioned at that 461 return;
409 // node, so there should be no valid pointers from the stack to a 462 NodeAllocator::traceValue(visitor, this);
410 // destructed node. 463 visitor->mark(next());
411 if (wasAlreadyDestructed()) 464 visitor->mark(prev());
412 return; 465 }
413 NodeAllocator::traceValue(visitor, this); 466
414 visitor->mark(next()); 467 ListHashSetNode* next() const {
415 visitor->mark(prev()); 468 return reinterpret_cast<ListHashSetNode*>(this->m_next);
416 } 469 }
417 470 ListHashSetNode* prev() const {
418 ListHashSetNode* next() const { return reinterpret_cast<ListHashSetNode*>(th is->m_next); } 471 return reinterpret_cast<ListHashSetNode*>(this->m_prev);
419 ListHashSetNode* prev() const { return reinterpret_cast<ListHashSetNode*>(th is->m_prev); } 472 }
420 473
421 // Don't add fields here, the ListHashSetNodeBase and this should have the 474 // Don't add fields here, the ListHashSetNodeBase and this should have the
422 // same size. 475 // same size.
423 476
424 static ListHashSetNode* unlinkedNodePointer() { return reinterpret_cast<List HashSetNode*>(-1); } 477 static ListHashSetNode* unlinkedNodePointer() {
425 478 return reinterpret_cast<ListHashSetNode*>(-1);
426 template <typename HashArg> 479 }
427 friend struct ListHashSetNodeHashFunctions; 480
428 }; 481 template <typename HashArg>
429 482 friend struct ListHashSetNodeHashFunctions;
430 template <typename HashArg> struct ListHashSetNodeHashFunctions { 483 };
431 STATIC_ONLY(ListHashSetNodeHashFunctions); 484
432 template <typename T> static unsigned hash(const T& key) { return HashArg::h ash(key->m_value); } 485 template <typename HashArg>
433 template <typename T> static bool equal(const T& a, const T& b) { return Has hArg::equal(a->m_value, b->m_value); } 486 struct ListHashSetNodeHashFunctions {
434 static const bool safeToCompareToEmptyOrDeleted = false; 487 STATIC_ONLY(ListHashSetNodeHashFunctions);
435 }; 488 template <typename T>
436 489 static unsigned hash(const T& key) {
437 template <typename Set> class ListHashSetIterator { 490 return HashArg::hash(key->m_value);
438 DISALLOW_NEW(); 491 }
439 private: 492 template <typename T>
440 typedef typename Set::const_iterator const_iterator; 493 static bool equal(const T& a, const T& b) {
441 typedef typename Set::Node Node; 494 return HashArg::equal(a->m_value, b->m_value);
442 typedef typename Set::ValueType ValueType; 495 }
443 typedef ValueType& ReferenceType; 496 static const bool safeToCompareToEmptyOrDeleted = false;
444 typedef ValueType* PointerType; 497 };
445 498
446 ListHashSetIterator(const Set* set, Node* position) : m_iterator(set, positi on) {} 499 template <typename Set>
447 500 class ListHashSetIterator {
448 public: 501 DISALLOW_NEW();
449 ListHashSetIterator() {} 502
450 503 private:
451 // default copy, assignment and destructor are OK 504 typedef typename Set::const_iterator const_iterator;
452 505 typedef typename Set::Node Node;
453 PointerType get() const { return const_cast<PointerType>(m_iterator.get()); } 506 typedef typename Set::ValueType ValueType;
454 ReferenceType operator*() const { return *get(); } 507 typedef ValueType& ReferenceType;
455 PointerType operator->() const { return get(); } 508 typedef ValueType* PointerType;
456 509
457 ListHashSetIterator& operator++() { ++m_iterator; return *this; } 510 ListHashSetIterator(const Set* set, Node* position)
458 ListHashSetIterator& operator--() { --m_iterator; return *this; } 511 : m_iterator(set, position) {}
459 512
460 // Postfix ++ and -- intentionally omitted. 513 public:
461 514 ListHashSetIterator() {}
462 // Comparison. 515
463 bool operator==(const ListHashSetIterator& other) const { return m_iterator == other.m_iterator; } 516 // default copy, assignment and destructor are OK
464 bool operator!=(const ListHashSetIterator& other) const { return m_iterator != other.m_iterator; } 517
465 518 PointerType get() const { return const_cast<PointerType>(m_iterator.get()); }
466 operator const_iterator() const { return m_iterator; } 519 ReferenceType operator*() const { return *get(); }
467 520 PointerType operator->() const { return get(); }
468 private: 521
469 Node* node() { return m_iterator.node(); } 522 ListHashSetIterator& operator++() {
470 523 ++m_iterator;
471 const_iterator m_iterator; 524 return *this;
472 525 }
473 template <typename T, size_t inlineCapacity, typename U, typename V> 526 ListHashSetIterator& operator--() {
474 friend class ListHashSet; 527 --m_iterator;
528 return *this;
529 }
530
531 // Postfix ++ and -- intentionally omitted.
532
533 // Comparison.
534 bool operator==(const ListHashSetIterator& other) const {
535 return m_iterator == other.m_iterator;
536 }
537 bool operator!=(const ListHashSetIterator& other) const {
538 return m_iterator != other.m_iterator;
539 }
540
541 operator const_iterator() const { return m_iterator; }
542
543 private:
544 Node* node() { return m_iterator.node(); }
545
546 const_iterator m_iterator;
547
548 template <typename T, size_t inlineCapacity, typename U, typename V>
549 friend class ListHashSet;
475 }; 550 };
476 551
477 template <typename Set> 552 template <typename Set>
478 class ListHashSetConstIterator { 553 class ListHashSetConstIterator {
479 DISALLOW_NEW(); 554 DISALLOW_NEW();
480 private: 555
481 typedef typename Set::const_iterator const_iterator; 556 private:
482 typedef typename Set::Node Node; 557 typedef typename Set::const_iterator const_iterator;
483 typedef typename Set::ValueType ValueType; 558 typedef typename Set::Node Node;
484 typedef const ValueType& ReferenceType; 559 typedef typename Set::ValueType ValueType;
485 typedef const ValueType* PointerType; 560 typedef const ValueType& ReferenceType;
486 561 typedef const ValueType* PointerType;
487 friend class ListHashSetIterator<Set>; 562
488 563 friend class ListHashSetIterator<Set>;
489 ListHashSetConstIterator(const Set* set, Node* position) 564
490 : m_set(set) 565 ListHashSetConstIterator(const Set* set, Node* position)
491 , m_position(position) 566 : m_set(set), m_position(position) {}
492 { 567
493 } 568 public:
494 569 ListHashSetConstIterator() {}
495 public: 570
496 ListHashSetConstIterator() 571 PointerType get() const { return &m_position->m_value; }
497 { 572 ReferenceType operator*() const { return *get(); }
498 } 573 PointerType operator->() const { return get(); }
499 574
500 PointerType get() const 575 ListHashSetConstIterator& operator++() {
501 { 576 ASSERT(m_position != 0);
502 return &m_position->m_value; 577 m_position = m_position->next();
503 } 578 return *this;
504 ReferenceType operator*() const { return *get(); } 579 }
505 PointerType operator->() const { return get(); } 580
506 581 ListHashSetConstIterator& operator--() {
507 ListHashSetConstIterator& operator++() 582 ASSERT(m_position != m_set->m_head);
508 { 583 if (!m_position)
509 ASSERT(m_position != 0); 584 m_position = m_set->m_tail;
510 m_position = m_position->next(); 585 else
511 return *this; 586 m_position = m_position->prev();
512 } 587 return *this;
513 588 }
514 ListHashSetConstIterator& operator--() 589
515 { 590 // Postfix ++ and -- intentionally omitted.
516 ASSERT(m_position != m_set->m_head); 591
517 if (!m_position) 592 // Comparison.
518 m_position = m_set->m_tail; 593 bool operator==(const ListHashSetConstIterator& other) const {
519 else 594 return m_position == other.m_position;
520 m_position = m_position->prev(); 595 }
521 return *this; 596 bool operator!=(const ListHashSetConstIterator& other) const {
522 } 597 return m_position != other.m_position;
523 598 }
524 // Postfix ++ and -- intentionally omitted. 599
525 600 private:
526 // Comparison. 601 Node* node() { return m_position; }
527 bool operator==(const ListHashSetConstIterator& other) const 602
528 { 603 const Set* m_set;
529 return m_position == other.m_position; 604 Node* m_position;
530 } 605
531 bool operator!=(const ListHashSetConstIterator& other) const 606 template <typename T, size_t inlineCapacity, typename U, typename V>
532 { 607 friend class ListHashSet;
533 return m_position != other.m_position;
534 }
535
536 private:
537 Node* node() { return m_position; }
538
539 const Set* m_set;
540 Node* m_position;
541
542 template <typename T, size_t inlineCapacity, typename U, typename V>
543 friend class ListHashSet;
544 }; 608 };
545 609
546 template <typename Set> 610 template <typename Set>
547 class ListHashSetReverseIterator { 611 class ListHashSetReverseIterator {
548 DISALLOW_NEW(); 612 DISALLOW_NEW();
549 private: 613
550 typedef typename Set::const_reverse_iterator const_reverse_iterator; 614 private:
551 typedef typename Set::Node Node; 615 typedef typename Set::const_reverse_iterator const_reverse_iterator;
552 typedef typename Set::ValueType ValueType; 616 typedef typename Set::Node Node;
553 typedef ValueType& ReferenceType; 617 typedef typename Set::ValueType ValueType;
554 typedef ValueType* PointerType; 618 typedef ValueType& ReferenceType;
555 619 typedef ValueType* PointerType;
556 ListHashSetReverseIterator(const Set* set, Node* position) : m_iterator(set, position) {} 620
557 621 ListHashSetReverseIterator(const Set* set, Node* position)
558 public: 622 : m_iterator(set, position) {}
559 ListHashSetReverseIterator() {} 623
560 624 public:
561 // default copy, assignment and destructor are OK 625 ListHashSetReverseIterator() {}
562 626
563 PointerType get() const { return const_cast<PointerType>(m_iterator.get()); } 627 // default copy, assignment and destructor are OK
564 ReferenceType operator*() const { return *get(); } 628
565 PointerType operator->() const { return get(); } 629 PointerType get() const { return const_cast<PointerType>(m_iterator.get()); }
566 630 ReferenceType operator*() const { return *get(); }
567 ListHashSetReverseIterator& operator++() { ++m_iterator; return *this; } 631 PointerType operator->() const { return get(); }
568 ListHashSetReverseIterator& operator--() { --m_iterator; return *this; } 632
569 633 ListHashSetReverseIterator& operator++() {
570 // Postfix ++ and -- intentionally omitted. 634 ++m_iterator;
571 635 return *this;
572 // Comparison. 636 }
573 bool operator==(const ListHashSetReverseIterator& other) const { return m_it erator == other.m_iterator; } 637 ListHashSetReverseIterator& operator--() {
574 bool operator!=(const ListHashSetReverseIterator& other) const { return m_it erator != other.m_iterator; } 638 --m_iterator;
575 639 return *this;
576 operator const_reverse_iterator() const { return m_iterator; } 640 }
577 641
578 private: 642 // Postfix ++ and -- intentionally omitted.
579 Node* node() { return m_iterator.node(); } 643
580 644 // Comparison.
581 const_reverse_iterator m_iterator; 645 bool operator==(const ListHashSetReverseIterator& other) const {
582 646 return m_iterator == other.m_iterator;
583 template <typename T, size_t inlineCapacity, typename U, typename V> 647 }
584 friend class ListHashSet; 648 bool operator!=(const ListHashSetReverseIterator& other) const {
585 }; 649 return m_iterator != other.m_iterator;
586 650 }
587 template <typename Set> class ListHashSetConstReverseIterator { 651
588 DISALLOW_NEW(); 652 operator const_reverse_iterator() const { return m_iterator; }
589 private: 653
590 typedef typename Set::reverse_iterator reverse_iterator; 654 private:
591 typedef typename Set::Node Node; 655 Node* node() { return m_iterator.node(); }
592 typedef typename Set::ValueType ValueType; 656
593 typedef const ValueType& ReferenceType; 657 const_reverse_iterator m_iterator;
594 typedef const ValueType* PointerType; 658
595 659 template <typename T, size_t inlineCapacity, typename U, typename V>
596 friend class ListHashSetReverseIterator<Set>; 660 friend class ListHashSet;
597 661 };
598 ListHashSetConstReverseIterator(const Set* set, Node* position) 662
599 : m_set(set) 663 template <typename Set>
600 , m_position(position) 664 class ListHashSetConstReverseIterator {
601 { 665 DISALLOW_NEW();
602 } 666
603 667 private:
604 public: 668 typedef typename Set::reverse_iterator reverse_iterator;
605 ListHashSetConstReverseIterator() 669 typedef typename Set::Node Node;
606 { 670 typedef typename Set::ValueType ValueType;
607 } 671 typedef const ValueType& ReferenceType;
608 672 typedef const ValueType* PointerType;
609 PointerType get() const 673
610 { 674 friend class ListHashSetReverseIterator<Set>;
611 return &m_position->m_value; 675
612 } 676 ListHashSetConstReverseIterator(const Set* set, Node* position)
613 ReferenceType operator*() const { return *get(); } 677 : m_set(set), m_position(position) {}
614 PointerType operator->() const { return get(); } 678
615 679 public:
616 ListHashSetConstReverseIterator& operator++() 680 ListHashSetConstReverseIterator() {}
617 { 681
618 ASSERT(m_position != 0); 682 PointerType get() const { return &m_position->m_value; }
619 m_position = m_position->prev(); 683 ReferenceType operator*() const { return *get(); }
620 return *this; 684 PointerType operator->() const { return get(); }
621 } 685
622 686 ListHashSetConstReverseIterator& operator++() {
623 ListHashSetConstReverseIterator& operator--() 687 ASSERT(m_position != 0);
624 { 688 m_position = m_position->prev();
625 ASSERT(m_position != m_set->m_tail); 689 return *this;
626 if (!m_position) 690 }
627 m_position = m_set->m_head; 691
628 else 692 ListHashSetConstReverseIterator& operator--() {
629 m_position = m_position->next(); 693 ASSERT(m_position != m_set->m_tail);
630 return *this; 694 if (!m_position)
631 } 695 m_position = m_set->m_head;
632 696 else
633 // Postfix ++ and -- intentionally omitted. 697 m_position = m_position->next();
634 698 return *this;
635 // Comparison. 699 }
636 bool operator==(const ListHashSetConstReverseIterator& other) const 700
637 { 701 // Postfix ++ and -- intentionally omitted.
638 return m_position == other.m_position; 702
639 } 703 // Comparison.
640 bool operator!=(const ListHashSetConstReverseIterator& other) const 704 bool operator==(const ListHashSetConstReverseIterator& other) const {
641 { 705 return m_position == other.m_position;
642 return m_position != other.m_position; 706 }
643 } 707 bool operator!=(const ListHashSetConstReverseIterator& other) const {
644 708 return m_position != other.m_position;
645 private: 709 }
646 Node* node() { return m_position; } 710
647 711 private:
648 const Set* m_set; 712 Node* node() { return m_position; }
649 Node* m_position; 713
650 714 const Set* m_set;
651 template <typename T, size_t inlineCapacity, typename U, typename V> 715 Node* m_position;
652 friend class ListHashSet; 716
717 template <typename T, size_t inlineCapacity, typename U, typename V>
718 friend class ListHashSet;
653 }; 719 };
654 720
655 template <typename HashFunctions> 721 template <typename HashFunctions>
656 struct ListHashSetTranslator { 722 struct ListHashSetTranslator {
657 STATIC_ONLY(ListHashSetTranslator); 723 STATIC_ONLY(ListHashSetTranslator);
658 template <typename T> static unsigned hash(const T& key) { return HashFuncti ons::hash(key); } 724 template <typename T>
659 template <typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a->m_value, b); } 725 static unsigned hash(const T& key) {
660 template <typename T, typename U, typename V> static void translate(T*& loca tion, const U& key, const V& allocator) 726 return HashFunctions::hash(key);
661 { 727 }
662 location = new (const_cast<V*>(&allocator)) T(key); 728 template <typename T, typename U>
663 } 729 static bool equal(const T& a, const U& b) {
730 return HashFunctions::equal(a->m_value, b);
731 }
732 template <typename T, typename U, typename V>
733 static void translate(T*& location, const U& key, const V& allocator) {
734 location = new (const_cast<V*>(&allocator)) T(key);
735 }
664 }; 736 };
665 737
666 template <typename T, size_t inlineCapacity, typename U, typename V> 738 template <typename T, size_t inlineCapacity, typename U, typename V>
667 inline ListHashSet<T, inlineCapacity, U, V>::ListHashSet() 739 inline ListHashSet<T, inlineCapacity, U, V>::ListHashSet()
668 : m_head(nullptr) 740 : m_head(nullptr), m_tail(nullptr) {}
669 , m_tail(nullptr) 741
670 { 742 template <typename T, size_t inlineCapacity, typename U, typename V>
671 } 743 inline ListHashSet<T, inlineCapacity, U, V>::ListHashSet(
672 744 const ListHashSet& other)
673 template <typename T, size_t inlineCapacity, typename U, typename V> 745 : m_head(nullptr), m_tail(nullptr) {
674 inline ListHashSet<T, inlineCapacity, U, V>::ListHashSet(const ListHashSet& othe r) 746 const_iterator end = other.end();
675 : m_head(nullptr) 747 for (const_iterator it = other.begin(); it != end; ++it)
676 , m_tail(nullptr) 748 add(*it);
677 { 749 }
678 const_iterator end = other.end(); 750
679 for (const_iterator it = other.begin(); it != end; ++it) 751 template <typename T, size_t inlineCapacity, typename U, typename V>
680 add(*it); 752 inline ListHashSet<T, inlineCapacity, U, V>&
681 } 753 ListHashSet<T, inlineCapacity, U, V>::operator=(const ListHashSet& other) {
682 754 ListHashSet tmp(other);
683 template <typename T, size_t inlineCapacity, typename U, typename V> 755 swap(tmp);
684 inline ListHashSet<T, inlineCapacity, U, V>& ListHashSet<T, inlineCapacity, U, V >::operator=(const ListHashSet& other) 756 return *this;
685 { 757 }
686 ListHashSet tmp(other); 758
687 swap(tmp); 759 template <typename T, size_t inlineCapacity, typename U, typename V>
688 return *this; 760 inline void ListHashSet<T, inlineCapacity, U, V>::swap(ListHashSet& other) {
689 } 761 m_impl.swap(other.m_impl);
690 762 std::swap(m_head, other.m_head);
691 template <typename T, size_t inlineCapacity, typename U, typename V> 763 std::swap(m_tail, other.m_tail);
692 inline void ListHashSet<T, inlineCapacity, U, V>::swap(ListHashSet& other) 764 m_allocatorProvider.swap(other.m_allocatorProvider);
693 { 765 }
694 m_impl.swap(other.m_impl); 766
695 std::swap(m_head, other.m_head); 767 template <typename T, size_t inlineCapacity, typename U, typename V>
696 std::swap(m_tail, other.m_tail); 768 inline void ListHashSet<T, inlineCapacity, U, V>::finalize() {
697 m_allocatorProvider.swap(other.m_allocatorProvider); 769 static_assert(!Allocator::isGarbageCollected,
698 } 770 "heap allocated ListHashSet should never call finalize()");
699 771 deleteAllNodes();
700 template <typename T, size_t inlineCapacity, typename U, typename V> 772 m_allocatorProvider.releaseAllocator();
701 inline void ListHashSet<T, inlineCapacity, U, V>::finalize() 773 }
702 { 774
703 static_assert(!Allocator::isGarbageCollected, "heap allocated ListHashSet sh ould never call finalize()"); 775 template <typename T, size_t inlineCapacity, typename U, typename V>
704 deleteAllNodes(); 776 inline T& ListHashSet<T, inlineCapacity, U, V>::first() {
705 m_allocatorProvider.releaseAllocator(); 777 ASSERT(!isEmpty());
706 } 778 return m_head->m_value;
707 779 }
708 template <typename T, size_t inlineCapacity, typename U, typename V> 780
709 inline T& ListHashSet<T, inlineCapacity, U, V>::first() 781 template <typename T, size_t inlineCapacity, typename U, typename V>
710 { 782 inline void ListHashSet<T, inlineCapacity, U, V>::removeFirst() {
711 ASSERT(!isEmpty()); 783 ASSERT(!isEmpty());
712 return m_head->m_value; 784 m_impl.remove(m_head);
713 } 785 unlinkAndDelete(m_head);
714 786 }
715 template <typename T, size_t inlineCapacity, typename U, typename V> 787
716 inline void ListHashSet<T, inlineCapacity, U, V>::removeFirst() 788 template <typename T, size_t inlineCapacity, typename U, typename V>
717 { 789 inline const T& ListHashSet<T, inlineCapacity, U, V>::first() const {
718 ASSERT(!isEmpty()); 790 ASSERT(!isEmpty());
719 m_impl.remove(m_head); 791 return m_head->m_value;
720 unlinkAndDelete(m_head); 792 }
721 } 793
722 794 template <typename T, size_t inlineCapacity, typename U, typename V>
723 template <typename T, size_t inlineCapacity, typename U, typename V> 795 inline T& ListHashSet<T, inlineCapacity, U, V>::last() {
724 inline const T& ListHashSet<T, inlineCapacity, U, V>::first() const 796 ASSERT(!isEmpty());
725 { 797 return m_tail->m_value;
726 ASSERT(!isEmpty()); 798 }
727 return m_head->m_value; 799
728 } 800 template <typename T, size_t inlineCapacity, typename U, typename V>
729 801 inline const T& ListHashSet<T, inlineCapacity, U, V>::last() const {
730 template <typename T, size_t inlineCapacity, typename U, typename V> 802 ASSERT(!isEmpty());
731 inline T& ListHashSet<T, inlineCapacity, U, V>::last() 803 return m_tail->m_value;
732 { 804 }
733 ASSERT(!isEmpty()); 805
734 return m_tail->m_value; 806 template <typename T, size_t inlineCapacity, typename U, typename V>
735 } 807 inline void ListHashSet<T, inlineCapacity, U, V>::removeLast() {
736 808 ASSERT(!isEmpty());
737 template <typename T, size_t inlineCapacity, typename U, typename V> 809 m_impl.remove(m_tail);
738 inline const T& ListHashSet<T, inlineCapacity, U, V>::last() const 810 unlinkAndDelete(m_tail);
739 { 811 }
740 ASSERT(!isEmpty()); 812
741 return m_tail->m_value; 813 template <typename T, size_t inlineCapacity, typename U, typename V>
742 } 814 inline typename ListHashSet<T, inlineCapacity, U, V>::iterator
743 815 ListHashSet<T, inlineCapacity, U, V>::find(ValuePeekInType value) {
744 template <typename T, size_t inlineCapacity, typename U, typename V> 816 ImplTypeIterator it = m_impl.template find<BaseTranslator>(value);
745 inline void ListHashSet<T, inlineCapacity, U, V>::removeLast() 817 if (it == m_impl.end())
746 { 818 return end();
747 ASSERT(!isEmpty()); 819 return makeIterator(*it);
748 m_impl.remove(m_tail); 820 }
749 unlinkAndDelete(m_tail); 821
750 } 822 template <typename T, size_t inlineCapacity, typename U, typename V>
751 823 inline typename ListHashSet<T, inlineCapacity, U, V>::const_iterator
752 template <typename T, size_t inlineCapacity, typename U, typename V> 824 ListHashSet<T, inlineCapacity, U, V>::find(ValuePeekInType value) const {
753 inline typename ListHashSet<T, inlineCapacity, U, V>::iterator ListHashSet<T, in lineCapacity, U, V>::find(ValuePeekInType value) 825 ImplTypeConstIterator it = m_impl.template find<BaseTranslator>(value);
754 { 826 if (it == m_impl.end())
755 ImplTypeIterator it = m_impl.template find<BaseTranslator>(value); 827 return end();
756 if (it == m_impl.end()) 828 return makeConstIterator(*it);
757 return end();
758 return makeIterator(*it);
759 }
760
761 template <typename T, size_t inlineCapacity, typename U, typename V>
762 inline typename ListHashSet<T, inlineCapacity, U, V>::const_iterator ListHashSet <T, inlineCapacity, U, V>::find(ValuePeekInType value) const
763 {
764 ImplTypeConstIterator it = m_impl.template find<BaseTranslator>(value);
765 if (it == m_impl.end())
766 return end();
767 return makeConstIterator(*it);
768 } 829 }
769 830
770 template <typename Translator> 831 template <typename Translator>
771 struct ListHashSetTranslatorAdapter { 832 struct ListHashSetTranslatorAdapter {
772 STATIC_ONLY(ListHashSetTranslatorAdapter); 833 STATIC_ONLY(ListHashSetTranslatorAdapter);
773 template <typename T> static unsigned hash(const T& key) { return Translator ::hash(key); } 834 template <typename T>
774 template <typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a->m_value, b); } 835 static unsigned hash(const T& key) {
836 return Translator::hash(key);
837 }
838 template <typename T, typename U>
839 static bool equal(const T& a, const U& b) {
840 return Translator::equal(a->m_value, b);
841 }
775 }; 842 };
776 843
777 template <typename ValueType, size_t inlineCapacity, typename U, typename V> 844 template <typename ValueType, size_t inlineCapacity, typename U, typename V>
778 template <typename HashTranslator, typename T> 845 template <typename HashTranslator, typename T>
779 inline typename ListHashSet<ValueType, inlineCapacity, U, V>::iterator ListHashS et<ValueType, inlineCapacity, U, V>::find(const T& value) 846 inline typename ListHashSet<ValueType, inlineCapacity, U, V>::iterator
780 { 847 ListHashSet<ValueType, inlineCapacity, U, V>::find(const T& value) {
781 ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter <HashTranslator>>(value); 848 ImplTypeConstIterator it =
782 if (it == m_impl.end()) 849 m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator>>(value);
783 return end(); 850 if (it == m_impl.end())
784 return makeIterator(*it); 851 return end();
852 return makeIterator(*it);
785 } 853 }
786 854
787 template <typename ValueType, size_t inlineCapacity, typename U, typename V> 855 template <typename ValueType, size_t inlineCapacity, typename U, typename V>
788 template <typename HashTranslator, typename T> 856 template <typename HashTranslator, typename T>
789 inline typename ListHashSet<ValueType, inlineCapacity, U, V>::const_iterator Lis tHashSet<ValueType, inlineCapacity, U, V>::find(const T& value) const 857 inline typename ListHashSet<ValueType, inlineCapacity, U, V>::const_iterator
790 { 858 ListHashSet<ValueType, inlineCapacity, U, V>::find(const T& value) const {
791 ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter <HashTranslator>>(value); 859 ImplTypeConstIterator it =
792 if (it == m_impl.end()) 860 m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator>>(value);
793 return end(); 861 if (it == m_impl.end())
794 return makeConstIterator(*it); 862 return end();
863 return makeConstIterator(*it);
795 } 864 }
796 865
797 template <typename ValueType, size_t inlineCapacity, typename U, typename V> 866 template <typename ValueType, size_t inlineCapacity, typename U, typename V>
798 template <typename HashTranslator, typename T> 867 template <typename HashTranslator, typename T>
799 inline bool ListHashSet<ValueType, inlineCapacity, U, V>::contains(const T& valu e) const 868 inline bool ListHashSet<ValueType, inlineCapacity, U, V>::contains(
800 { 869 const T& value) const {
801 return m_impl.template contains<ListHashSetTranslatorAdapter<HashTranslator> >(value); 870 return m_impl.template contains<ListHashSetTranslatorAdapter<HashTranslator>>(
802 } 871 value);
803 872 }
804 template <typename T, size_t inlineCapacity, typename U, typename V> 873
805 inline bool ListHashSet<T, inlineCapacity, U, V>::contains(ValuePeekInType value ) const 874 template <typename T, size_t inlineCapacity, typename U, typename V>
806 { 875 inline bool ListHashSet<T, inlineCapacity, U, V>::contains(
807 return m_impl.template contains<BaseTranslator>(value); 876 ValuePeekInType value) const {
808 } 877 return m_impl.template contains<BaseTranslator>(value);
809 878 }
810 template <typename T, size_t inlineCapacity, typename U, typename V> 879
811 typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCa pacity, U, V>::add(ValuePassInType value) 880 template <typename T, size_t inlineCapacity, typename U, typename V>
812 { 881 typename ListHashSet<T, inlineCapacity, U, V>::AddResult
813 createAllocatorIfNeeded(); 882 ListHashSet<T, inlineCapacity, U, V>::add(ValuePassInType value) {
814 // The second argument is a const ref. This is useful for the HashTable 883 createAllocatorIfNeeded();
815 // because it lets it take lvalues by reference, but for our purposes it's 884 // The second argument is a const ref. This is useful for the HashTable
816 // inconvenient, since it constrains us to be const, whereas the allocator 885 // because it lets it take lvalues by reference, but for our purposes it's
817 // actually changes when it does allocations. 886 // inconvenient, since it constrains us to be const, whereas the allocator
818 auto result = m_impl.template add<BaseTranslator>(value, *this->allocator()) ; 887 // actually changes when it does allocations.
819 if (result.isNewEntry) 888 auto result = m_impl.template add<BaseTranslator>(value, *this->allocator());
820 appendNode(*result.storedValue); 889 if (result.isNewEntry)
821 return AddResult(*result.storedValue, result.isNewEntry); 890 appendNode(*result.storedValue);
822 } 891 return AddResult(*result.storedValue, result.isNewEntry);
823 892 }
824 template <typename T, size_t inlineCapacity, typename U, typename V> 893
825 typename ListHashSet<T, inlineCapacity, U, V>::iterator ListHashSet<T, inlineCap acity, U, V>::addReturnIterator(ValuePassInType value) 894 template <typename T, size_t inlineCapacity, typename U, typename V>
826 { 895 typename ListHashSet<T, inlineCapacity, U, V>::iterator
827 return makeIterator(add(value).storedValue); 896 ListHashSet<T, inlineCapacity, U, V>::addReturnIterator(ValuePassInType value) {
828 } 897 return makeIterator(add(value).storedValue);
829 898 }
830 template <typename T, size_t inlineCapacity, typename U, typename V> 899
831 typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCa pacity, U, V>::appendOrMoveToLast(ValuePassInType value) 900 template <typename T, size_t inlineCapacity, typename U, typename V>
832 { 901 typename ListHashSet<T, inlineCapacity, U, V>::AddResult
833 createAllocatorIfNeeded(); 902 ListHashSet<T, inlineCapacity, U, V>::appendOrMoveToLast(
834 auto result = m_impl.template add<BaseTranslator>(value, *this->allocator()) ; 903 ValuePassInType value) {
835 Node* node = *result.storedValue; 904 createAllocatorIfNeeded();
836 if (!result.isNewEntry) 905 auto result = m_impl.template add<BaseTranslator>(value, *this->allocator());
837 unlink(node); 906 Node* node = *result.storedValue;
838 appendNode(node); 907 if (!result.isNewEntry)
839 return AddResult(*result.storedValue, result.isNewEntry); 908 unlink(node);
840 } 909 appendNode(node);
841 910 return AddResult(*result.storedValue, result.isNewEntry);
842 template <typename T, size_t inlineCapacity, typename U, typename V> 911 }
843 typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCa pacity, U, V>::prependOrMoveToFirst(ValuePassInType value) 912
844 { 913 template <typename T, size_t inlineCapacity, typename U, typename V>
845 createAllocatorIfNeeded(); 914 typename ListHashSet<T, inlineCapacity, U, V>::AddResult
846 auto result = m_impl.template add<BaseTranslator>(value, *this->allocator()) ; 915 ListHashSet<T, inlineCapacity, U, V>::prependOrMoveToFirst(
847 Node* node = *result.storedValue; 916 ValuePassInType value) {
848 if (!result.isNewEntry) 917 createAllocatorIfNeeded();
849 unlink(node); 918 auto result = m_impl.template add<BaseTranslator>(value, *this->allocator());
850 prependNode(node); 919 Node* node = *result.storedValue;
851 return AddResult(*result.storedValue, result.isNewEntry); 920 if (!result.isNewEntry)
852 } 921 unlink(node);
853 922 prependNode(node);
854 template <typename T, size_t inlineCapacity, typename U, typename V> 923 return AddResult(*result.storedValue, result.isNewEntry);
855 typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCa pacity, U, V>::insertBefore(iterator it, ValuePassInType newValue) 924 }
856 { 925
857 createAllocatorIfNeeded(); 926 template <typename T, size_t inlineCapacity, typename U, typename V>
858 auto result = m_impl.template add<BaseTranslator>(newValue, *this->allocator ()); 927 typename ListHashSet<T, inlineCapacity, U, V>::AddResult
859 if (result.isNewEntry) 928 ListHashSet<T, inlineCapacity, U, V>::insertBefore(iterator it,
860 insertNodeBefore(it.node(), *result.storedValue); 929 ValuePassInType newValue) {
861 return AddResult(*result.storedValue, result.isNewEntry); 930 createAllocatorIfNeeded();
862 } 931 auto result =
863 932 m_impl.template add<BaseTranslator>(newValue, *this->allocator());
864 template <typename T, size_t inlineCapacity, typename U, typename V> 933 if (result.isNewEntry)
865 typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCa pacity, U, V>::insertBefore(ValuePeekInType beforeValue, ValuePassInType newValu e) 934 insertNodeBefore(it.node(), *result.storedValue);
866 { 935 return AddResult(*result.storedValue, result.isNewEntry);
867 createAllocatorIfNeeded(); 936 }
868 return insertBefore(find(beforeValue), newValue); 937
869 } 938 template <typename T, size_t inlineCapacity, typename U, typename V>
870 939 typename ListHashSet<T, inlineCapacity, U, V>::AddResult
871 template <typename T, size_t inlineCapacity, typename U, typename V> 940 ListHashSet<T, inlineCapacity, U, V>::insertBefore(ValuePeekInType beforeValue,
872 inline void ListHashSet<T, inlineCapacity, U, V>::remove(iterator it) 941 ValuePassInType newValue) {
873 { 942 createAllocatorIfNeeded();
874 if (it == end()) 943 return insertBefore(find(beforeValue), newValue);
875 return; 944 }
876 m_impl.remove(it.node()); 945
877 unlinkAndDelete(it.node()); 946 template <typename T, size_t inlineCapacity, typename U, typename V>
878 } 947 inline void ListHashSet<T, inlineCapacity, U, V>::remove(iterator it) {
879 948 if (it == end())
880 template <typename T, size_t inlineCapacity, typename U, typename V> 949 return;
881 inline void ListHashSet<T, inlineCapacity, U, V>::clear() 950 m_impl.remove(it.node());
882 { 951 unlinkAndDelete(it.node());
883 deleteAllNodes(); 952 }
884 m_impl.clear(); 953
885 m_head = nullptr; 954 template <typename T, size_t inlineCapacity, typename U, typename V>
886 m_tail = nullptr; 955 inline void ListHashSet<T, inlineCapacity, U, V>::clear() {
887 } 956 deleteAllNodes();
888 957 m_impl.clear();
889 template <typename T, size_t inlineCapacity, typename U, typename V> 958 m_head = nullptr;
890 typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType ListHashSet<T, i nlineCapacity, U, V>::take(iterator it) 959 m_tail = nullptr;
891 { 960 }
892 if (it == end()) 961
893 return ValueTraits::emptyValue(); 962 template <typename T, size_t inlineCapacity, typename U, typename V>
894 963 typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType
895 m_impl.remove(it.node()); 964 ListHashSet<T, inlineCapacity, U, V>::take(iterator it) {
896 ValuePassOutType result = ValueTraits::passOut(it.node()->m_value); 965 if (it == end())
897 unlinkAndDelete(it.node()); 966 return ValueTraits::emptyValue();
898 967
899 return result; 968 m_impl.remove(it.node());
900 } 969 ValuePassOutType result = ValueTraits::passOut(it.node()->m_value);
901 970 unlinkAndDelete(it.node());
902 template <typename T, size_t inlineCapacity, typename U, typename V> 971
903 typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType ListHashSet<T, i nlineCapacity, U, V>::take(ValuePeekInType value) 972 return result;
904 { 973 }
905 return take(find(value)); 974
906 } 975 template <typename T, size_t inlineCapacity, typename U, typename V>
907 976 typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType
908 template <typename T, size_t inlineCapacity, typename U, typename V> 977 ListHashSet<T, inlineCapacity, U, V>::take(ValuePeekInType value) {
909 typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType ListHashSet<T, i nlineCapacity, U, V>::takeFirst() 978 return take(find(value));
910 { 979 }
911 ASSERT(!isEmpty()); 980
912 m_impl.remove(m_head); 981 template <typename T, size_t inlineCapacity, typename U, typename V>
913 ValuePassOutType result = ValueTraits::passOut(m_head->m_value); 982 typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType
914 unlinkAndDelete(m_head); 983 ListHashSet<T, inlineCapacity, U, V>::takeFirst() {
915 984 ASSERT(!isEmpty());
916 return result; 985 m_impl.remove(m_head);
986 ValuePassOutType result = ValueTraits::passOut(m_head->m_value);
987 unlinkAndDelete(m_head);
988
989 return result;
917 } 990 }
918 991
919 template <typename T, size_t inlineCapacity, typename U, typename Allocator> 992 template <typename T, size_t inlineCapacity, typename U, typename Allocator>
920 void ListHashSet<T, inlineCapacity, U, Allocator>::unlink(Node* node) 993 void ListHashSet<T, inlineCapacity, U, Allocator>::unlink(Node* node) {
921 { 994 if (!node->m_prev) {
922 if (!node->m_prev) { 995 ASSERT(node == m_head);
923 ASSERT(node == m_head); 996 m_head = node->next();
924 m_head = node->next(); 997 } else {
925 } else { 998 ASSERT(node != m_head);
926 ASSERT(node != m_head); 999 node->m_prev->m_next = node->m_next;
927 node->m_prev->m_next = node->m_next; 1000 }
928 } 1001
929 1002 if (!node->m_next) {
930 if (!node->m_next) { 1003 ASSERT(node == m_tail);
931 ASSERT(node == m_tail); 1004 m_tail = node->prev();
932 m_tail = node->prev(); 1005 } else {
933 } else { 1006 ASSERT(node != m_tail);
934 ASSERT(node != m_tail); 1007 node->m_next->m_prev = node->m_prev;
935 node->m_next->m_prev = node->m_prev; 1008 }
936 } 1009 }
937 } 1010
938 1011 template <typename T, size_t inlineCapacity, typename U, typename V>
939 template <typename T, size_t inlineCapacity, typename U, typename V> 1012 void ListHashSet<T, inlineCapacity, U, V>::unlinkAndDelete(Node* node) {
940 void ListHashSet<T, inlineCapacity, U, V>::unlinkAndDelete(Node* node) 1013 unlink(node);
941 { 1014 node->destroy(this->allocator());
942 unlink(node); 1015 }
1016
1017 template <typename T, size_t inlineCapacity, typename U, typename V>
1018 void ListHashSet<T, inlineCapacity, U, V>::appendNode(Node* node) {
1019 node->m_prev = m_tail;
1020 node->m_next = nullptr;
1021
1022 if (m_tail) {
1023 ASSERT(m_head);
1024 m_tail->m_next = node;
1025 } else {
1026 ASSERT(!m_head);
1027 m_head = node;
1028 }
1029
1030 m_tail = node;
1031 }
1032
1033 template <typename T, size_t inlineCapacity, typename U, typename V>
1034 void ListHashSet<T, inlineCapacity, U, V>::prependNode(Node* node) {
1035 node->m_prev = nullptr;
1036 node->m_next = m_head;
1037
1038 if (m_head)
1039 m_head->m_prev = node;
1040 else
1041 m_tail = node;
1042
1043 m_head = node;
1044 }
1045
1046 template <typename T, size_t inlineCapacity, typename U, typename V>
1047 void ListHashSet<T, inlineCapacity, U, V>::insertNodeBefore(Node* beforeNode,
1048 Node* newNode) {
1049 if (!beforeNode)
1050 return appendNode(newNode);
1051
1052 newNode->m_next = beforeNode;
1053 newNode->m_prev = beforeNode->m_prev;
1054 if (beforeNode->m_prev)
1055 beforeNode->m_prev->m_next = newNode;
1056 beforeNode->m_prev = newNode;
1057
1058 if (!newNode->m_prev)
1059 m_head = newNode;
1060 }
1061
1062 template <typename T, size_t inlineCapacity, typename U, typename V>
1063 void ListHashSet<T, inlineCapacity, U, V>::deleteAllNodes() {
1064 if (!m_head)
1065 return;
1066
1067 for (Node *node = m_head, *next = m_head->next(); node;
1068 node = next, next = node ? node->next() : 0)
943 node->destroy(this->allocator()); 1069 node->destroy(this->allocator());
944 } 1070 }
945 1071
946 template <typename T, size_t inlineCapacity, typename U, typename V> 1072 template <typename T, size_t inlineCapacity, typename U, typename V>
947 void ListHashSet<T, inlineCapacity, U, V>::appendNode(Node* node)
948 {
949 node->m_prev = m_tail;
950 node->m_next = nullptr;
951
952 if (m_tail) {
953 ASSERT(m_head);
954 m_tail->m_next = node;
955 } else {
956 ASSERT(!m_head);
957 m_head = node;
958 }
959
960 m_tail = node;
961 }
962
963 template <typename T, size_t inlineCapacity, typename U, typename V>
964 void ListHashSet<T, inlineCapacity, U, V>::prependNode(Node* node)
965 {
966 node->m_prev = nullptr;
967 node->m_next = m_head;
968
969 if (m_head)
970 m_head->m_prev = node;
971 else
972 m_tail = node;
973
974 m_head = node;
975 }
976
977 template <typename T, size_t inlineCapacity, typename U, typename V>
978 void ListHashSet<T, inlineCapacity, U, V>::insertNodeBefore(Node* beforeNode, No de* newNode)
979 {
980 if (!beforeNode)
981 return appendNode(newNode);
982
983 newNode->m_next = beforeNode;
984 newNode->m_prev = beforeNode->m_prev;
985 if (beforeNode->m_prev)
986 beforeNode->m_prev->m_next = newNode;
987 beforeNode->m_prev = newNode;
988
989 if (!newNode->m_prev)
990 m_head = newNode;
991 }
992
993 template <typename T, size_t inlineCapacity, typename U, typename V>
994 void ListHashSet<T, inlineCapacity, U, V>::deleteAllNodes()
995 {
996 if (!m_head)
997 return;
998
999 for (Node* node = m_head, *next = m_head->next(); node; node = next, next = node ? node->next() : 0)
1000 node->destroy(this->allocator());
1001 }
1002
1003 template <typename T, size_t inlineCapacity, typename U, typename V>
1004 template <typename VisitorDispatcher> 1073 template <typename VisitorDispatcher>
1005 void ListHashSet<T, inlineCapacity, U, V>::trace(VisitorDispatcher visitor) 1074 void ListHashSet<T, inlineCapacity, U, V>::trace(VisitorDispatcher visitor) {
1006 { 1075 static_assert(HashTraits<T>::weakHandlingFlag == NoWeakHandlingInCollections,
1007 static_assert(HashTraits<T>::weakHandlingFlag == NoWeakHandlingInCollections , "ListHashSet does not support weakness"); 1076 "ListHashSet does not support weakness");
1008 // This marks all the nodes and their contents live that can be accessed 1077 // This marks all the nodes and their contents live that can be accessed
1009 // through the HashTable. That includes m_head and m_tail so we do not have 1078 // through the HashTable. That includes m_head and m_tail so we do not have
1010 // to explicitly trace them here. 1079 // to explicitly trace them here.
1011 m_impl.trace(visitor); 1080 m_impl.trace(visitor);
1012 } 1081 }
1013 1082
1014 #if !ENABLE(OILPAN) 1083 #if !ENABLE(OILPAN)
1015 template <typename T, size_t U, typename V> 1084 template <typename T, size_t U, typename V>
1016 struct NeedsTracing<ListHashSet<T, U, V>> { 1085 struct NeedsTracing<ListHashSet<T, U, V>> {
1017 static const bool value = false; 1086 static const bool value = false;
1018 }; 1087 };
1019 #endif 1088 #endif
1020 1089
1021 } // namespace WTF 1090 } // namespace WTF
1022 1091
1023 using WTF::ListHashSet; 1092 using WTF::ListHashSet;
1024 1093
1025 #endif // WTF_ListHashSet_h 1094 #endif // WTF_ListHashSet_h
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/LinkedStack.h ('k') | third_party/WebKit/Source/wtf/ListHashSetTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698