source: webkit/trunk/JavaScriptCore/wtf/HashTable.h@ 15241

Last change on this file since 15241 was 14256, checked in by mjs, 19 years ago

JavaScriptCore:

Rubber stamped by Anders.


  • renamed kxmlcore to wtf


kxmlcore --> wtf
KXMLCore --> WTF
WKC --> WTF

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bindings/c/c_instance.cpp:
  • bindings/objc/WebScriptObject.mm:
  • kjs/JSImmediate.h:
  • kjs/Parser.cpp:
  • kjs/Parser.h:
  • kjs/array_object.cpp:
  • kjs/collector.cpp: (KJS::Collector::registerThread):
  • kjs/collector.h:
  • kjs/config.h:
  • kjs/function.cpp: (KJS::isStrWhiteSpace):
  • kjs/function.h:
  • kjs/identifier.cpp:
  • kjs/internal.cpp:
  • kjs/internal.h:
  • kjs/lexer.cpp: (Lexer::shift): (Lexer::isWhiteSpace): (Lexer::isIdentStart): (Lexer::isIdentPart):
  • kjs/lookup.cpp:
  • kjs/nodes.cpp:
  • kjs/nodes.h:
  • kjs/number_object.cpp:
  • kjs/object.h:
  • kjs/property_map.cpp:
  • kjs/property_map.h:
  • kjs/string_object.cpp: (StringProtoFunc::callAsFunction):
  • kjs/testkjs.cpp: (testIsInteger):
  • kjs/ustring.cpp:
  • kjs/ustring.h:
  • kxmlcore: Removed.
  • kxmlcore/AlwaysInline.h: Removed.
  • kxmlcore/Assertions.cpp: Removed.
  • kxmlcore/Assertions.h: Removed.
  • kxmlcore/FastMalloc.cpp: Removed.
  • kxmlcore/FastMalloc.h: Removed.
  • kxmlcore/FastMallocInternal.h: Removed.
  • kxmlcore/Forward.h: Removed.
  • kxmlcore/HashCountedSet.h: Removed.
  • kxmlcore/HashFunctions.h: Removed.
  • kxmlcore/HashMap.h: Removed.
  • kxmlcore/HashSet.h: Removed.
  • kxmlcore/HashTable.cpp: Removed.
  • kxmlcore/HashTable.h: Removed.
  • kxmlcore/HashTraits.h: Removed.
  • kxmlcore/ListRefPtr.h: Removed.
  • kxmlcore/Noncopyable.h: Removed.
  • kxmlcore/OwnArrayPtr.h: Removed.
  • kxmlcore/OwnPtr.h: Removed.
  • kxmlcore/PassRefPtr.h: Removed.
  • kxmlcore/Platform.h: Removed.
  • kxmlcore/RefPtr.h: Removed.
  • kxmlcore/TCPageMap.h: Removed.
  • kxmlcore/TCSpinLock.h: Removed.
  • kxmlcore/TCSystemAlloc.cpp: Removed.
  • kxmlcore/TCSystemAlloc.h: Removed.
  • kxmlcore/UnusedParam.h: Removed.
  • kxmlcore/Vector.h: Removed.
  • kxmlcore/VectorTraits.h: Removed.
  • kxmlcore/unicode: Removed.
  • kxmlcore/unicode/Unicode.h: Removed.
  • kxmlcore/unicode/UnicodeCategory.h: Removed.
  • kxmlcore/unicode/icu: Removed.
  • kxmlcore/unicode/icu/UnicodeIcu.h: Removed.
  • kxmlcore/unicode/posix: Removed.
  • kxmlcore/unicode/qt3: Removed.
  • kxmlcore/unicode/qt4: Removed.
  • kxmlcore/unicode/qt4/UnicodeQt4.h: Removed.
  • pcre/pcre_get.c:
  • wtf: Added.
  • wtf/Assertions.cpp:
  • wtf/Assertions.h:
  • wtf/FastMalloc.cpp: (WTF::TCMalloc_ThreadCache::Scavenge): (WTF::do_malloc): (WTF::do_free): (WTF::TCMallocGuard::TCMallocGuard): (WTF::malloc): (WTF::free): (WTF::calloc): (WTF::cfree): (WTF::realloc):
  • wtf/FastMalloc.h:
  • wtf/FastMallocInternal.h:
  • wtf/Forward.h:
  • wtf/HashCountedSet.h:
  • wtf/HashFunctions.h:
  • wtf/HashMap.h:
  • wtf/HashSet.h:
  • wtf/HashTable.cpp:
  • wtf/HashTable.h:
  • wtf/HashTraits.h:
  • wtf/ListRefPtr.h:
  • wtf/Noncopyable.h:
  • wtf/OwnArrayPtr.h:
  • wtf/OwnPtr.h:
  • wtf/PassRefPtr.h:
  • wtf/RefPtr.h:
  • wtf/TCSystemAlloc.cpp: (TCMalloc_SystemAlloc):
  • wtf/Vector.h:
  • wtf/VectorTraits.h:
  • wtf/unicode/UnicodeCategory.h:
  • wtf/unicode/icu/UnicodeIcu.h:

JavaScriptGlue:

Rubber stamped by Anders.


  • renamed kxmlcore to wtf


kxmlcore --> wtf
KXMLCore --> WTF
WKC --> WTF

  • config.h:
  • kxmlcore: Removed.
  • kxmlcore/AlwaysInline.h: Removed.
  • kxmlcore/Assertions.h: Removed.
  • kxmlcore/FastMalloc.h: Removed.
  • kxmlcore/Forward.h: Removed.
  • kxmlcore/HashCountedSet.h: Removed.
  • kxmlcore/HashSet.h: Removed.
  • kxmlcore/Noncopyable.h: Removed.
  • kxmlcore/OwnArrayPtr.h: Removed.
  • kxmlcore/OwnPtr.h: Removed.
  • kxmlcore/PassRefPtr.h: Removed.
  • kxmlcore/Platform.h: Removed.
  • kxmlcore/RefPtr.h: Removed.
  • kxmlcore/Vector.h: Removed.
  • wtf: Added.

WebCore:

Rubber stamped by Anders.


  • renamed kxmlcore to wtf


kxmlcore --> wtf
KXMLCore --> WTF
WKC --> WTF

  • ForwardingHeaders/kxmlcore: Removed.
  • ForwardingHeaders/kxmlcore/AlwaysInline.h: Removed.
  • ForwardingHeaders/kxmlcore/Assertions.h: Removed.
  • ForwardingHeaders/kxmlcore/FastMalloc.h: Removed.
  • ForwardingHeaders/kxmlcore/Forward.h: Removed.
  • ForwardingHeaders/kxmlcore/HashCountedSet.h: Removed.
  • ForwardingHeaders/kxmlcore/HashMap.h: Removed.
  • ForwardingHeaders/kxmlcore/HashSet.h: Removed.
  • ForwardingHeaders/kxmlcore/HashTraits.h: Removed.
  • ForwardingHeaders/kxmlcore/Noncopyable.h: Removed.
  • ForwardingHeaders/kxmlcore/OwnArrayPtr.h: Removed.
  • ForwardingHeaders/kxmlcore/OwnPtr.h: Removed.
  • ForwardingHeaders/kxmlcore/PassRefPtr.h: Removed.
  • ForwardingHeaders/kxmlcore/Platform.h: Removed.
  • ForwardingHeaders/kxmlcore/RefPtr.h: Removed.
  • ForwardingHeaders/kxmlcore/Vector.h: Removed.
  • ForwardingHeaders/wtf: Added.
  • bindings/js/JSHTMLElementWrapperFactory.h:
  • bindings/js/kjs_binding.cpp:
  • bindings/js/kjs_window.h:
  • bindings/objc/DOMImplementationFront.h:
  • bridge/JavaAppletWidget.h:
  • bridge/mac/WebCoreFrameNamespaces.mm:
  • bridge/mac/WebCorePageBridge.mm: (initializeLogChannel):
  • bridge/mac/WebCoreStringTruncator.mm:
  • bridge/mac/WebCoreViewFactory.m:
  • config.h:
  • css/css_base.h:
  • css/css_valueimpl.h:
  • css/csshelper.cpp:
  • css/cssparser.h:
  • dom/DOMImplementation.h:
  • dom/Document.h:
  • dom/NamedNodeMap.h:
  • dom/Node.h:
  • dom/NodeList.h:
  • dom/QualifiedName.cpp:
  • dom/Range.h:
  • dom/StyledElement.cpp:
  • dom/dom2_traversalimpl.h:
  • dom/xml_tokenizer.h:
  • editing/RebalanceWhitespaceCommand.cpp:
  • editing/RemoveCSSPropertyCommand.cpp:
  • editing/RemoveNodeAttributeCommand.cpp:
  • editing/RemoveNodeCommand.cpp:
  • editing/RemoveNodePreservingChildrenCommand.cpp:
  • editing/ReplaceSelectionCommand.h:
  • editing/Selection.cpp:
  • editing/SetNodeAttributeCommand.cpp:
  • editing/SplitElementCommand.cpp:
  • editing/SplitTextNodeCommand.cpp:
  • editing/SplitTextNodeContainingElementCommand.cpp:
  • editing/TextIterator.h:
  • editing/htmlediting.h:
  • editing/markup.h:
  • html/CanvasGradient.h:
  • html/CanvasRenderingContext2D.h:
  • html/CanvasStyle.cpp:
  • html/HTMLCollection.h:
  • html/HTMLElementFactory.h:
  • kcanvas/KCanvasFilters.cpp:
  • kcanvas/KCanvasPath.h:
  • kcanvas/RenderPath.cpp:
  • kcanvas/RenderSVGImage.cpp:
  • kcanvas/RenderSVGText.cpp:
  • kcanvas/device/quartz/KCanvasItemQuartz.mm:
  • kcanvas/device/quartz/KRenderingPaintServerGradientQuartz.mm:
  • kcanvas/device/quartz/QuartzSupport.mm:
  • ksvg2/misc/KSVGTimeScheduler.h:
  • ksvg2/misc/SVGDocumentExtensions.h:
  • ksvg2/scripts/make_names.pl:
  • ksvg2/svg/SVGDOMImplementation.cpp:
  • ksvg2/svg/SVGExternalResourcesRequired.h:
  • ksvg2/svg/SVGFilterPrimitiveStandardAttributes.cpp:
  • ksvg2/svg/SVGForeignObjectElement.cpp:
  • ksvg2/svg/SVGImageElement.cpp:
  • ksvg2/svg/SVGMaskElement.cpp:
  • ksvg2/svg/SVGStyledElement.cpp:
  • ksvg2/svg/SVGTests.h:
  • ksvg2/svg/SVGTransform.h:
  • ksvg2/svg/SVGTransformable.cpp:
  • kwq/AccessibilityObjectCache.h:
  • kwq/KWQCString.cpp:
  • kwq/KWQFormData.mm:
  • kwq/KWQListBox.mm:
  • kwq/KWQResourceLoader.mm:
  • kwq/KWQTextEdit.mm:
  • loader/Cache.h:
  • loader/CachedObject.h:
  • loader/CachedObjectClientWalker.h:
  • loader/Decoder.h:
  • loader/DocLoader.h:
  • loader/loader.cpp:
  • loader/loader.h:
  • page/DOMWindow.h:
  • page/Frame.h:
  • page/FramePrivate.h:
  • page/FrameTree.cpp:
  • page/Page.cpp:
  • page/Page.h:
  • page/Plugin.h:
  • platform/Arena.cpp:
  • platform/ArrayImpl.h:
  • platform/AtomicString.cpp:
  • platform/CharsetNames.cpp:
  • platform/Color.cpp:
  • platform/DeprecatedPtrListImpl.cpp:
  • platform/DeprecatedValueListImpl.h:
  • platform/FontFallbackList.h:
  • platform/GraphicsContext.h:
  • platform/GraphicsTypes.cpp:
  • platform/Image.h:
  • platform/KURL.cpp:
  • platform/Logging.cpp:
  • platform/Logging.h:
  • platform/PlatformString.h:
  • platform/PlugInInfoStore.h:
  • platform/StreamingTextDecoder.cpp:
  • platform/StreamingTextDecoder.h:
  • platform/String.cpp:
  • platform/StringHash.h:
  • platform/StringImpl.cpp:
  • platform/StringImpl.h:
  • platform/TextEncoding.cpp:
  • platform/Timer.cpp:
  • platform/Timer.h:
  • platform/TransferJob.h:
  • platform/TransferJobInternal.h:
  • platform/mac/BlockExceptions.mm:
  • platform/mac/ColorMac.mm:
  • platform/mac/FontData.mm:
  • platform/mac/KURLMac.mm:
  • platform/mac/QStringMac.mm:
  • platform/mac/SharedTimerMac.cpp:
  • platform/mac/TextEncodingMac.cpp:
  • platform/mac/WebCoreImageRendererFactory.m:
  • platform/mac/WebCoreKeyGenerator.m:
  • platform/mac/WebCoreTextArea.mm:
  • platform/mac/WebCoreTextField.mm:
  • platform/mac/WebTextRendererFactory.h:
  • platform/mac/WebTextRendererFactory.mm:
  • platform/win/TemporaryLinkStubs.cpp: (JavaAppletWidget::JavaAppletWidget):
  • rendering/InlineTextBox.cpp:
  • rendering/RenderText.cpp:
  • rendering/RenderTreeAsText.cpp:
  • rendering/bidi.cpp:
  • xml/XSLTProcessor.h:
  • xpath/impl/XPathExpressionNode.h:
  • xpath/impl/XPathParser.h:
  • xpath/impl/XPathPath.h:
  • xpath/impl/XPathUtil.h:

WebKit:

Rubber stamped by Anders.


  • renamed kxmlcore to wtf


kxmlcore --> wtf
KXMLCore --> WTF
WKC --> WTF

  • Misc/WebKitLogging.h:
  • Misc/WebKitLogging.m: (initializeLogChannel):
  • Property svn:eol-style set to native
File size: 35.6 KB
Line 
1// -*- mode: c++; c-basic-offset: 4 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 2005, 2006 Apple Computer, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#ifndef KXMLCORE_HASH_TABLE_H
24#define KXMLCORE_HASH_TABLE_H
25
26#include "FastMalloc.h"
27#include "HashTraits.h"
28#include <assert.h>
29
30namespace WTF {
31
32#define DUMP_HASHTABLE_STATS 0
33#define CHECK_HASHTABLE_CONSISTENCY 0
34
35#ifdef NDEBUG
36#define CHECK_HASHTABLE_ITERATORS 0
37#else
38#define CHECK_HASHTABLE_ITERATORS 1
39#endif
40
41#if DUMP_HASHTABLE_STATS
42
43 struct HashTableStats {
44 ~HashTableStats();
45 static int numAccesses;
46 static int numCollisions;
47 static int collisionGraph[4096];
48 static int maxCollisions;
49 static int numRehashes;
50 static int numRemoves;
51 static int numReinserts;
52 static void recordCollisionAtCount(int count);
53 };
54
55#endif
56
57 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
58 class HashTable;
59 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
60 class HashTableIterator;
61 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
62 class HashTableConstIterator;
63
64#if CHECK_HASHTABLE_ITERATORS
65 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
66 void addIterator(const HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*,
67 HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*);
68
69 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
70 void removeIterator(HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*);
71#else
72 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
73 inline void addIterator(const HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*,
74 HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*) { }
75
76 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
77 inline void removeIterator(HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*) { }
78#endif
79
80 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
81 class HashTableConstIterator {
82 private:
83 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> HashTableType;
84 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> iterator;
85 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> const_iterator;
86 typedef Value ValueType;
87 typedef const ValueType& ReferenceType;
88 typedef const ValueType* PointerType;
89
90 friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>;
91 friend class HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>;
92
93 void skipEmptyBuckets()
94 {
95 while (m_position != m_endPosition && HashTableType::isEmptyOrDeletedBucket(*m_position))
96 ++m_position;
97 }
98
99 HashTableConstIterator(const HashTableType* table, PointerType position, PointerType endPosition)
100 : m_position(position), m_endPosition(endPosition)
101 {
102 addIterator(table, this);
103 skipEmptyBuckets();
104 }
105
106 public:
107 HashTableConstIterator()
108 {
109 addIterator(0, this);
110 }
111
112 // default copy, assignment and destructor are OK if CHECK_HASHTABLE_ITERATORS is 0
113
114#if CHECK_HASHTABLE_ITERATORS
115 ~HashTableConstIterator()
116 {
117 removeIterator(this);
118 }
119
120 HashTableConstIterator(const const_iterator& other)
121 : m_position(other.m_position), m_endPosition(other.m_endPosition)
122 {
123 addIterator(other.m_table, this);
124 }
125
126 const_iterator& operator=(const const_iterator& other)
127 {
128 m_position = other.m_position;
129 m_endPosition = other.m_endPosition;
130
131 removeIterator(this);
132 addIterator(other.m_table, this);
133
134 return *this;
135 }
136#endif
137
138 PointerType get() const
139 {
140 checkValidity();
141 return m_position;
142 }
143 ReferenceType operator*() const { return *get(); }
144 PointerType operator->() const { return get(); }
145
146 const_iterator& operator++()
147 {
148 checkValidity();
149 assert(m_position != m_endPosition);
150 ++m_position;
151 skipEmptyBuckets();
152 return *this;
153 }
154
155 // postfix ++ intentionally omitted
156
157 // Comparison.
158 bool operator==(const const_iterator& other) const
159 {
160 checkValidity(other);
161 return m_position == other.m_position;
162 }
163 bool operator!=(const const_iterator& other) const
164 {
165 checkValidity(other);
166 return m_position != other.m_position;
167 }
168
169 private:
170 void checkValidity() const
171 {
172#if CHECK_HASHTABLE_ITERATORS
173 assert(m_table);
174#endif
175 }
176
177
178#if CHECK_HASHTABLE_ITERATORS
179 void checkValidity(const const_iterator& other) const
180 {
181 assert(m_table);
182 assert(other.m_table);
183 assert(m_table == other.m_table);
184 }
185#else
186 void checkValidity(const const_iterator&) const { }
187#endif
188
189 PointerType m_position;
190 PointerType m_endPosition;
191
192#if CHECK_HASHTABLE_ITERATORS
193 public:
194 mutable const HashTableType* m_table;
195 mutable const_iterator* m_next;
196 mutable const_iterator* m_previous;
197#endif
198 };
199
200 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
201 class HashTableIterator {
202 private:
203 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> HashTableType;
204 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> iterator;
205 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> const_iterator;
206 typedef Value ValueType;
207 typedef ValueType& ReferenceType;
208 typedef ValueType* PointerType;
209
210 friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>;
211
212 HashTableIterator(HashTableType* table, PointerType pos, PointerType end) : m_iterator(table, pos, end) { }
213
214 public:
215 HashTableIterator() { }
216
217 // default copy, assignment and destructor are OK
218
219 PointerType get() const { return const_cast<PointerType>(m_iterator.get()); }
220 ReferenceType operator*() const { return *get(); }
221 PointerType operator->() const { return get(); }
222
223 iterator& operator++() { ++m_iterator; return *this; }
224
225 // postfix ++ intentionally omitted
226
227 // Comparison.
228 bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; }
229 bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; }
230
231 operator const_iterator() const { return m_iterator; }
232
233 private:
234 const_iterator m_iterator;
235 };
236
237 using std::swap;
238
239#if !COMPILER(MSVC)
240 // Visual C++ has a swap for pairs defined.
241
242 // swap pairs by component, in case of pair members that specialize swap
243 template<typename T, typename U> inline void swap(pair<T, U>& a, pair<T, U>& b)
244 {
245 swap(a.first, b.first);
246 swap(a.second, b.second);
247 }
248#endif
249
250 template<typename T, bool useSwap> struct Mover;
251 template<typename T> struct Mover<T, true> { static void move(T& from, T& to) { swap(from, to); } };
252 template<typename T> struct Mover<T, false> { static void move(T& from, T& to) { to = from; } };
253
254 template<typename Key, typename Value, typename HashFunctions> class IdentityHashTranslator {
255 public:
256 static unsigned hash(const Key& key) { return HashFunctions::hash(key); }
257 static bool equal(const Key& a, const Key& b) { return HashFunctions::equal(a, b); }
258 static void translate(Value& location, const Key&, const Value& value, unsigned) { location = value; }
259 };
260
261 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
262 class HashTable {
263 public:
264 typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> iterator;
265 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> const_iterator;
266 typedef Traits ValueTraits;
267 typedef Key KeyType;
268 typedef Value ValueType;
269 typedef IdentityHashTranslator<Key, Value, HashFunctions> IdentityTranslatorType;
270
271 HashTable();
272 ~HashTable() { invalidateIterators(); deallocateTable(m_table, m_tableSize); }
273
274 HashTable(const HashTable&);
275 void swap(HashTable&);
276 HashTable& operator=(const HashTable&);
277
278 iterator begin() { return makeIterator(m_table); }
279 iterator end() { return makeIterator(m_table + m_tableSize); }
280 const_iterator begin() const { return makeConstIterator(m_table); }
281 const_iterator end() const { return makeConstIterator(m_table + m_tableSize); }
282
283 int size() const { return m_keyCount; }
284 int capacity() const { return m_tableSize; }
285 bool isEmpty() const { return !m_keyCount; }
286
287 pair<iterator, bool> add(const ValueType& value) { return add<KeyType, ValueType, IdentityTranslatorType>(Extractor::extract(value), value); }
288
289 // A special version of add() that finds the object by hashing and comparing
290 // with some other type, to avoid the cost of type conversion if the object is already
291 // in the table.
292 template<typename T, typename Extra, typename HashTranslator> pair<iterator, bool> add(const T& key, const Extra&);
293
294 iterator find(const KeyType&);
295 const_iterator find(const KeyType&) const;
296 bool contains(const KeyType&) const;
297
298 void remove(const KeyType&);
299 void remove(iterator);
300 void clear();
301
302 static bool isEmptyBucket(const ValueType& value) { return Extractor::extract(value) == KeyTraits::emptyValue(); }
303 static bool isDeletedBucket(const ValueType& value) { return Extractor::extract(value) == KeyTraits::deletedValue(); }
304 static bool isEmptyOrDeletedBucket(const ValueType& value) { return isEmptyBucket(value) || isDeletedBucket(value); }
305
306 private:
307 static ValueType* allocateTable(int size);
308 static void deallocateTable(ValueType* table, int size);
309
310 typedef pair<ValueType*, bool> LookupType;
311 typedef pair<LookupType, unsigned> FullLookupType;
312
313 LookupType lookup(const Key& key) { return lookup<Key, IdentityTranslatorType>(key).first; }
314 template<typename T, typename HashTranslator> FullLookupType lookup(const T&);
315
316 void remove(ValueType*);
317
318 bool shouldExpand() const { return (m_keyCount + m_deletedCount) * m_maxLoad >= m_tableSize; }
319 bool mustRehashInPlace() const { return m_keyCount * m_minLoad < m_tableSize * 2; }
320 bool shouldShrink() const { return m_keyCount * m_minLoad < m_tableSize && m_tableSize > m_minTableSize; }
321 void expand();
322 void shrink() { rehash(m_tableSize / 2); }
323
324 void rehash(int newTableSize);
325 void reinsert(ValueType&);
326
327 static void initializeBucket(ValueType& bucket) { new (&bucket) ValueType(Traits::emptyValue()); }
328 static void deleteBucket(ValueType& bucket) { assignDeleted<ValueType, Traits>(bucket); }
329
330 FullLookupType makeLookupResult(ValueType* position, bool found, unsigned hash)
331 { return FullLookupType(LookupType(position, found), hash); }
332
333 iterator makeIterator(ValueType* pos) { return iterator(this, pos, m_table + m_tableSize); }
334 const_iterator makeConstIterator(ValueType* pos) const { return const_iterator(this, pos, m_table + m_tableSize); }
335
336#if CHECK_HASHTABLE_CONSISTENCY
337 void checkTableConsistency() const;
338 void checkTableConsistencyExceptSize() const;
339#else
340 static void checkTableConsistency() { }
341 static void checkTableConsistencyExceptSize() { }
342#endif
343
344#if CHECK_HASHTABLE_ITERATORS
345 void invalidateIterators();
346#else
347 static void invalidateIterators() { }
348#endif
349
350 static const int m_minTableSize = 64;
351 static const int m_maxLoad = 2;
352 static const int m_minLoad = 6;
353
354 ValueType* m_table;
355 int m_tableSize;
356 int m_tableSizeMask;
357 int m_keyCount;
358 int m_deletedCount;
359
360#if CHECK_HASHTABLE_ITERATORS
361 public:
362 mutable const_iterator* m_iterators;
363#endif
364 };
365
366 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
367 inline HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::HashTable()
368 : m_table(0)
369 , m_tableSize(0)
370 , m_tableSizeMask(0)
371 , m_keyCount(0)
372 , m_deletedCount(0)
373#if CHECK_HASHTABLE_ITERATORS
374 , m_iterators(0)
375#endif
376 {
377 }
378
379 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
380 template<typename T, typename HashTranslator>
381 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::lookup(const T& key)
382 {
383 assert(m_table);
384
385 unsigned h = HashTranslator::hash(key);
386 int sizeMask = m_tableSizeMask;
387 int i = h & sizeMask;
388 int k = 0;
389
390#if DUMP_HASHTABLE_STATS
391 ++HashTableStats::numAccesses;
392 int probeCount = 0;
393#endif
394
395 ValueType *table = m_table;
396 ValueType *entry;
397 ValueType *deletedEntry = 0;
398 while (!isEmptyBucket(*(entry = table + i))) {
399 if (isDeletedBucket(*entry))
400 deletedEntry = entry;
401 else if (HashTranslator::equal(Extractor::extract(*entry), key))
402 return makeLookupResult(entry, true, h);
403#if DUMP_HASHTABLE_STATS
404 ++probeCount;
405 HashTableStats::recordCollisionAtCount(probeCount);
406#endif
407 if (k == 0)
408 k = 1 | (h % sizeMask);
409 i = (i + k) & sizeMask;
410 }
411
412 return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h);
413 }
414
415
416 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
417 template<typename T, typename Extra, typename HashTranslator>
418 inline pair<typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::iterator, bool> HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::add(const T& key, const Extra &extra)
419 {
420 invalidateIterators();
421
422 if (!m_table)
423 expand();
424
425 checkTableConsistency();
426
427 FullLookupType lookupResult = lookup<T, HashTranslator>(key);
428
429 ValueType *entry = lookupResult.first.first;
430 bool found = lookupResult.first.second;
431 unsigned h = lookupResult.second;
432
433 if (found)
434 return std::make_pair(makeIterator(entry), false);
435
436 if (isDeletedBucket(*entry))
437 --m_deletedCount;
438
439 HashTranslator::translate(*entry, key, extra, h);
440 ++m_keyCount;
441
442 if (shouldExpand()) {
443 // FIXME: this makes an extra copy on expand. Probably not that bad since
444 // expand is rare, but would be better to have a version of expand that can
445 // follow a pivot entry and return the new position
446 KeyType enteredKey = Extractor::extract(*entry);
447 expand();
448 return std::make_pair(find(enteredKey), true);
449 }
450
451 checkTableConsistency();
452
453 return std::make_pair(makeIterator(entry), true);
454 }
455
456 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
457 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::reinsert(ValueType& entry)
458 {
459 assert(m_table);
460 assert(!lookup(Extractor::extract(entry)).second);
461 assert(!isDeletedBucket(*(lookup(Extractor::extract(entry)).first)));
462#if DUMP_HASHTABLE_STATS
463 ++HashTableStats::numReinserts;
464#endif
465
466 Mover<ValueType, Traits::needsDestruction>::move(entry, *(lookup(Extractor::extract(entry)).first));
467 }
468
469 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
470 typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::iterator HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::find(const Key& key)
471 {
472 if (!m_table)
473 return end();
474
475 LookupType result = lookup(key);
476 if (!result.second)
477 return end();
478 return makeIterator(result.first);
479 }
480
481 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
482 typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::const_iterator HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::find(const Key& key) const
483 {
484 if (!m_table)
485 return end();
486
487 LookupType result = const_cast<HashTable *>(this)->lookup(key);
488 if (!result.second)
489 return end();
490 return makeConstIterator(result.first);
491 }
492
493 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
494 bool HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::contains(const KeyType& key) const
495 {
496 if (!m_table)
497 return false;
498
499 return const_cast<HashTable *>(this)->lookup(key).second;
500 }
501
502 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
503 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::remove(ValueType* pos)
504 {
505 invalidateIterators();
506 checkTableConsistency();
507
508#if DUMP_HASHTABLE_STATS
509 ++HashTableStats::numRemoves;
510#endif
511
512 deleteBucket(*pos);
513 ++m_deletedCount;
514 --m_keyCount;
515
516 if (shouldShrink())
517 shrink();
518
519 checkTableConsistency();
520 }
521
522 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
523 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::remove(iterator it)
524 {
525 if (it == end())
526 return;
527
528 remove(const_cast<ValueType*>(it.m_iterator.m_position));
529 }
530
531 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
532 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::remove(const KeyType& key)
533 {
534 remove(find(key));
535 }
536
537 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
538 Value *HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::allocateTable(int size)
539 {
540 // would use a template member function with explicit specializations here, but
541 // gcc doesn't appear to support that
542 if (Traits::emptyValueIsZero)
543 return static_cast<ValueType *>(fastCalloc(size, sizeof(ValueType)));
544 ValueType* result = static_cast<ValueType*>(fastMalloc(size * sizeof(ValueType)));
545 for (int i = 0; i < size; i++)
546 initializeBucket(result[i]);
547 return result;
548 }
549
550 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
551 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::deallocateTable(ValueType *table, int size)
552 {
553 if (Traits::needsDestruction)
554 for (int i = 0; i < size; ++i)
555 table[i].~ValueType();
556 fastFree(table);
557 }
558
559 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
560 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::expand()
561 {
562 int newSize;
563 if (m_tableSize == 0)
564 newSize = m_minTableSize;
565 else if (mustRehashInPlace())
566 newSize = m_tableSize;
567 else
568 newSize = m_tableSize * 2;
569
570 rehash(newSize);
571 }
572
573 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
574 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::rehash(int newTableSize)
575 {
576 checkTableConsistencyExceptSize();
577
578 int oldTableSize = m_tableSize;
579 ValueType *oldTable = m_table;
580
581#if DUMP_HASHTABLE_STATS
582 if (oldTableSize != 0)
583 ++HashTableStats::numRehashes;
584#endif
585
586 m_tableSize = newTableSize;
587 m_tableSizeMask = newTableSize - 1;
588 m_table = allocateTable(newTableSize);
589
590 for (int i = 0; i != oldTableSize; ++i)
591 if (!isEmptyOrDeletedBucket(oldTable[i]))
592 reinsert(oldTable[i]);
593
594 m_deletedCount = 0;
595
596 deallocateTable(oldTable, oldTableSize);
597
598 checkTableConsistency();
599 }
600
601 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
602 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::clear()
603 {
604 invalidateIterators();
605 deallocateTable(m_table, m_tableSize);
606 m_table = 0;
607 m_tableSize = 0;
608 m_tableSizeMask = 0;
609 m_keyCount = 0;
610 }
611
612 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
613 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::HashTable(const HashTable& other)
614 : m_table(0)
615 , m_tableSize(0)
616 , m_tableSizeMask(0)
617 , m_keyCount(0)
618 , m_deletedCount(0)
619#if CHECK_HASHTABLE_ITERATORS
620 , m_iterators(0)
621#endif
622 {
623 // Copy the hash table the dumb way, by adding each element to the new table.
624 // It might be more efficient to copy the table slots, but it's not clear that efficiency is needed.
625 const_iterator end = other.end();
626 for (const_iterator it = other.begin(); it != end; ++it)
627 add(*it);
628 }
629
630 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
631 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::swap(HashTable& other)
632 {
633 invalidateIterators();
634 other.invalidateIterators();
635
636 ValueType *tmp_table = m_table;
637 m_table = other.m_table;
638 other.m_table = tmp_table;
639
640 int tmp_tableSize = m_tableSize;
641 m_tableSize = other.m_tableSize;
642 other.m_tableSize = tmp_tableSize;
643
644 int tmp_tableSizeMask = m_tableSizeMask;
645 m_tableSizeMask = other.m_tableSizeMask;
646 other.m_tableSizeMask = tmp_tableSizeMask;
647
648 int tmp_keyCount = m_keyCount;
649 m_keyCount = other.m_keyCount;
650 other.m_keyCount = tmp_keyCount;
651
652 int tmp_deletedCount = m_deletedCount;
653 m_deletedCount = other.m_deletedCount;
654 other.m_deletedCount = tmp_deletedCount;
655 }
656
657 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
658 HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>& HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::operator=(const HashTable& other)
659 {
660 HashTable tmp(other);
661 swap(tmp);
662 return *this;
663 }
664
665#if CHECK_HASHTABLE_CONSISTENCY
666
667 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
668 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkTableConsistency() const
669 {
670 checkTableConsistencyExceptSize();
671 assert(!shouldExpand());
672 assert(!shouldShrink());
673 }
674
675 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
676 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkTableConsistencyExceptSize() const
677 {
678 if (!m_table)
679 return;
680
681 int count = 0;
682 int deletedCount = 0;
683 for (int j = 0; j < m_tableSize; ++j) {
684 ValueType *entry = m_table + j;
685 if (isEmptyBucket(*entry))
686 continue;
687
688 if (isDeletedBucket(*entry)) {
689 ++deletedCount;
690 continue;
691 }
692
693 const_iterator it = find(Extractor::extract(*entry));
694 assert(entry == it.m_position);
695 ++count;
696 }
697
698 assert(count == m_keyCount);
699 assert(deletedCount == m_deletedCount);
700 assert(m_tableSize >= m_minTableSize);
701 assert(m_tableSizeMask);
702 assert(m_tableSize == m_tableSizeMask + 1);
703 }
704
705#endif // CHECK_HASHTABLE_CONSISTENCY
706
707#if CHECK_HASHTABLE_ITERATORS
708
709 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
710 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::invalidateIterators()
711 {
712 const_iterator* next;
713 for (const_iterator* p = m_iterators; p; p = next) {
714 next = p->m_next;
715 p->m_table = 0;
716 p->m_next = 0;
717 p->m_previous = 0;
718 }
719 m_iterators = 0;
720 }
721
722 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
723 void addIterator(const HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>* table,
724 HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>* it)
725 {
726 it->m_table = table;
727 it->m_previous = 0;
728
729 // Insert iterator at head of doubly-linked list of iterators.
730 if (!table) {
731 it->m_next = 0;
732 } else {
733 assert(table->m_iterators != it);
734 it->m_next = table->m_iterators;
735 table->m_iterators = it;
736 if (it->m_next) {
737 assert(!it->m_next->m_previous);
738 it->m_next->m_previous = it;
739 }
740 }
741 }
742
743 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
744 void removeIterator(HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>* it)
745 {
746 typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> HashTableType;
747 typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> const_iterator;
748
749 // Delete iterator from doubly-linked list of iterators.
750 if (!it->m_table) {
751 assert(!it->m_next);
752 assert(!it->m_previous);
753 } else {
754 if (it->m_next) {
755 assert(it->m_next->m_previous == it);
756 it->m_next->m_previous = it->m_previous;
757 }
758 if (it->m_previous) {
759 assert(it->m_table->m_iterators != it);
760 assert(it->m_previous->m_next == it);
761 it->m_previous->m_next = it->m_next;
762 } else {
763 assert(it->m_table->m_iterators == it);
764 it->m_table->m_iterators = it->m_next;
765 }
766 }
767
768 it->m_table = 0;
769 it->m_next = 0;
770 it->m_previous = 0;
771 }
772
773#endif // CHECK_HASHTABLE_ITERATORS
774
775 // iterator adapters
776
777 template<typename HashTableType, typename ValueType> struct HashTableConstIteratorAdapter {
778 HashTableConstIteratorAdapter(const typename HashTableType::const_iterator& impl) : m_impl(impl) {}
779
780 const ValueType* get() const { return (const ValueType*)m_impl.get(); }
781 const ValueType& operator*() const { return *get(); }
782 const ValueType* operator->() const { return get(); }
783
784 HashTableConstIteratorAdapter& operator++() { ++m_impl; return *this; }
785 // postfix ++ intentionally omitted
786
787 typename HashTableType::const_iterator m_impl;
788 };
789
790 template<typename HashTableType, typename ValueType> struct HashTableIteratorAdapter {
791 HashTableIteratorAdapter(const typename HashTableType::iterator& impl) : m_impl(impl) {}
792
793 ValueType* get() const { return (ValueType*)m_impl.get(); }
794 ValueType& operator*() const { return *get(); }
795 ValueType* operator->() const { return get(); }
796
797 HashTableIteratorAdapter& operator++() { ++m_impl; return *this; }
798 // postfix ++ intentionally omitted
799
800 operator HashTableConstIteratorAdapter<HashTableType, ValueType>() {
801 typename HashTableType::const_iterator i = m_impl;
802 return i;
803 }
804
805 typename HashTableType::iterator m_impl;
806 };
807
808 template<typename T, typename U>
809 inline bool operator==(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
810 {
811 return a.m_impl == b.m_impl;
812 }
813
814 template<typename T, typename U>
815 inline bool operator!=(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
816 {
817 return a.m_impl != b.m_impl;
818 }
819
820 template<typename T, typename U>
821 inline bool operator==(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
822 {
823 return a.m_impl == b.m_impl;
824 }
825
826 template<typename T, typename U>
827 inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
828 {
829 return a.m_impl != b.m_impl;
830 }
831
832 // reference count manager
833
834 template<typename ValueTraits, typename ValueStorageTraits> struct NeedsRef {
835 static const bool value = ValueTraits::needsRef && !ValueStorageTraits::needsRef;
836 };
837 template<typename FirstTraits, typename SecondTraits, typename ValueStorageTraits>
838 struct NeedsRef<PairBaseHashTraits<FirstTraits, SecondTraits>, ValueStorageTraits> {
839 typedef typename ValueStorageTraits::FirstTraits FirstStorageTraits;
840 typedef typename ValueStorageTraits::SecondTraits SecondStorageTraits;
841 static const bool firstNeedsRef = NeedsRef<FirstTraits, FirstStorageTraits>::value;
842 static const bool secondNeedsRef = NeedsRef<SecondTraits, SecondStorageTraits>::value;
843 static const bool value = firstNeedsRef || secondNeedsRef;
844 };
845
846 template<bool needsRef, typename ValueTraits> struct RefCounterBase;
847
848 template<typename ValueTraits>
849 struct RefCounterBase<false, ValueTraits> {
850 typedef typename ValueTraits::TraitType ValueType;
851 static void ref(const ValueType&) { }
852 static void deref(const ValueType&) { }
853 };
854
855 template<typename ValueTraits>
856 struct RefCounterBase<true, ValueTraits> {
857 typedef typename ValueTraits::TraitType ValueType;
858 static void ref(const ValueType& v) { ValueTraits::ref(*(const ValueType*)&v); }
859 static void deref(const ValueType& v) { ValueTraits::deref(*(const ValueType*)&v); }
860 };
861
862 template<typename ValueTraits, typename ValueStorageTraits> struct RefCounter {
863 typedef typename ValueTraits::TraitType ValueType;
864 typedef typename ValueStorageTraits::TraitType ValueStorageType;
865 static const bool needsRef = NeedsRef<ValueTraits, ValueStorageTraits>::value;
866 typedef RefCounterBase<needsRef, ValueTraits> Base;
867 static void ref(const ValueStorageType& v) { Base::ref(*(const ValueType*)&v); }
868 static void deref(const ValueStorageType& v) { Base::deref(*(const ValueType*)&v); }
869 };
870
871 template<typename FirstTraits, typename SecondTraits, typename ValueStorageTraits>
872 struct RefCounter<PairBaseHashTraits<FirstTraits, SecondTraits>, ValueStorageTraits> {
873 typedef typename FirstTraits::TraitType FirstType;
874 typedef typename SecondTraits::TraitType SecondType;
875 typedef typename ValueStorageTraits::FirstTraits FirstStorageTraits;
876 typedef typename ValueStorageTraits::SecondTraits SecondStorageTraits;
877 typedef typename ValueStorageTraits::TraitType ValueStorageType;
878 static const bool firstNeedsRef = NeedsRef<FirstTraits, FirstStorageTraits>::value;
879 static const bool secondNeedsRef = NeedsRef<SecondTraits, SecondStorageTraits>::value;
880 typedef RefCounterBase<firstNeedsRef, FirstTraits> FirstBase;
881 typedef RefCounterBase<secondNeedsRef, SecondTraits> SecondBase;
882 static void ref(const ValueStorageType& v) {
883 FirstBase::ref(*(const FirstType*)&v.first);
884 SecondBase::ref(*(const SecondType*)&v.second);
885 }
886 static void deref(const ValueStorageType& v) {
887 FirstBase::deref(*(const FirstType*)&v.first);
888 SecondBase::deref(*(const SecondType*)&v.second);
889 }
890 };
891
892 template<bool needsRef, typename HashTableType, typename ValueTraits> struct HashTableRefCounterBase;
893
894 template<typename HashTableType, typename ValueTraits>
895 struct HashTableRefCounterBase<false, HashTableType, ValueTraits>
896 {
897 static void refAll(HashTableType&) { }
898 static void derefAll(HashTableType&) { }
899 };
900
901 template<typename HashTableType, typename ValueTraits>
902 struct HashTableRefCounterBase<true, HashTableType, ValueTraits>
903 {
904 typedef typename HashTableType::iterator iterator;
905 typedef RefCounter<ValueTraits, typename HashTableType::ValueTraits> ValueRefCounter;
906 static void refAll(HashTableType&);
907 static void derefAll(HashTableType&);
908 };
909
910 template<typename HashTableType, typename ValueTraits>
911 void HashTableRefCounterBase<true, HashTableType, ValueTraits>::refAll(HashTableType& table)
912 {
913 iterator end = table.end();
914 for (iterator it = table.begin(); it != end; ++it)
915 ValueRefCounter::ref(*it);
916 }
917
918 template<typename HashTableType, typename ValueTraits>
919 void HashTableRefCounterBase<true, HashTableType, ValueTraits>::derefAll(HashTableType& table)
920 {
921 iterator end = table.end();
922 for (iterator it = table.begin(); it != end; ++it)
923 ValueRefCounter::deref(*it);
924 }
925
926 template<typename HashTableType, typename ValueTraits> struct HashTableRefCounter {
927 static const bool needsRef = NeedsRef<ValueTraits, typename HashTableType::ValueTraits>::value;
928 typedef HashTableRefCounterBase<needsRef, HashTableType, ValueTraits> Base;
929 static void refAll(HashTableType& table) { Base::refAll(table); }
930 static void derefAll(HashTableType& table) { Base::derefAll(table); }
931 };
932
933} // namespace WTF
934
935#endif // KXMLCORE_HASH_TABLE_H
Note: See TracBrowser for help on using the repository browser.