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

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

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