diff options
Diffstat (limited to 'chromium/third_party/WebKit/Source/wtf/ListHashSet.h')
-rw-r--r-- | chromium/third_party/WebKit/Source/wtf/ListHashSet.h | 809 |
1 files changed, 440 insertions, 369 deletions
diff --git a/chromium/third_party/WebKit/Source/wtf/ListHashSet.h b/chromium/third_party/WebKit/Source/wtf/ListHashSet.h index 44d649259b6..7e26077e8d3 100644 --- a/chromium/third_party/WebKit/Source/wtf/ListHashSet.h +++ b/chromium/third_party/WebKit/Source/wtf/ListHashSet.h @@ -22,6 +22,7 @@ #ifndef WTF_ListHashSet_h #define WTF_ListHashSet_h +#include "wtf/DefaultAllocator.h" #include "wtf/HashSet.h" #include "wtf/OwnPtr.h" #include "wtf/PassOwnPtr.h" @@ -38,73 +39,101 @@ namespace WTF { // guaranteed safe against mutation of the ListHashSet, except for // removal of the item currently pointed to by a given iterator. - template<typename Value, size_t inlineCapacity, typename HashFunctions> class ListHashSet; + template<typename Value, size_t inlineCapacity, typename HashFunctions, typename Allocator> class ListHashSet; - template<typename Value, size_t inlineCapacity, typename HashFunctions> - void deleteAllValues(const ListHashSet<Value, inlineCapacity, HashFunctions>&); + template<typename Set> class ListHashSetIterator; + template<typename Set> class ListHashSetConstIterator; + template<typename Set> class ListHashSetReverseIterator; + template<typename Set> class ListHashSetConstReverseIterator; - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetIterator; - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstIterator; - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetReverseIterator; - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstReverseIterator; - - template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNode; - template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNodeAllocator; + template<typename ValueArg> class ListHashSetNodeBase; + template<typename ValueArg, typename Allocator> class ListHashSetNode; + template<typename ValueArg, size_t inlineCapacity> struct ListHashSetAllocator; template<typename HashArg> struct ListHashSetNodeHashFunctions; template<typename HashArg> struct ListHashSetTranslator; - template<typename ValueArg, size_t inlineCapacity = 256, typename HashArg = typename DefaultHash<ValueArg>::Hash> class ListHashSet { - WTF_MAKE_FAST_ALLOCATED; - private: - typedef ListHashSetNode<ValueArg, inlineCapacity> Node; - typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator; + // Don't declare a destructor for HeapAllocated ListHashSet. + template<typename Derived, typename Allocator, bool isGarbageCollected> + class ListHashSetDestructorBase; + + template<typename Derived, typename Allocator> + class ListHashSetDestructorBase<Derived, Allocator, true> { + protected: + typename Allocator::AllocatorProvider m_allocatorProvider; + }; + + template<typename Derived, typename Allocator> + class ListHashSetDestructorBase<Derived, Allocator, false> { + public: + ~ListHashSetDestructorBase() { static_cast<Derived*>(this)->finalize(); } + protected: + typename Allocator::AllocatorProvider m_allocatorProvider; + }; + + // Note that for a ListHashSet you cannot specify the HashTraits as a + // template argument. It uses the default hash traits for the ValueArg + // type. + template<typename ValueArg, size_t inlineCapacity = 256, typename HashArg = typename DefaultHash<ValueArg>::Hash, typename AllocatorArg = ListHashSetAllocator<ValueArg, inlineCapacity> > class ListHashSet + : public ListHashSetDestructorBase<ListHashSet<ValueArg, inlineCapacity, HashArg, AllocatorArg>, AllocatorArg, AllocatorArg::isGarbageCollected> { + typedef AllocatorArg Allocator; + WTF_USE_ALLOCATOR(ListHashSet, Allocator); + typedef ListHashSetNode<ValueArg, Allocator> Node; typedef HashTraits<Node*> NodeTraits; typedef ListHashSetNodeHashFunctions<HashArg> NodeHash; typedef ListHashSetTranslator<HashArg> BaseTranslator; - typedef HashTable<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits> ImplType; - typedef HashTableIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits> ImplTypeIterator; - typedef HashTableConstIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits> ImplTypeConstIterator; + typedef HashTable<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits, typename Allocator::TableAllocator> ImplType; + typedef HashTableIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits, typename Allocator::TableAllocator> ImplTypeIterator; + typedef HashTableConstIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits, typename Allocator::TableAllocator> ImplTypeConstIterator; typedef HashArg HashFunctions; public: typedef ValueArg ValueType; - - typedef ListHashSetIterator<ValueType, inlineCapacity, HashArg> iterator; - typedef ListHashSetConstIterator<ValueType, inlineCapacity, HashArg> const_iterator; - friend class ListHashSetConstIterator<ValueType, inlineCapacity, HashArg>; - - typedef ListHashSetReverseIterator<ValueType, inlineCapacity, HashArg> reverse_iterator; - typedef ListHashSetConstReverseIterator<ValueType, inlineCapacity, HashArg> const_reverse_iterator; - friend class ListHashSetConstReverseIterator<ValueType, inlineCapacity, HashArg>; - - typedef HashTableAddResult<iterator> AddResult; + typedef HashTraits<ValueType> ValueTraits; + typedef typename ValueTraits::PeekInType ValuePeekInType; + typedef typename ValueTraits::PassInType ValuePassInType; + typedef typename ValueTraits::PassOutType ValuePassOutType; + + typedef ListHashSetIterator<ListHashSet> iterator; + typedef ListHashSetConstIterator<ListHashSet> const_iterator; + friend class ListHashSetIterator<ListHashSet>; + friend class ListHashSetConstIterator<ListHashSet>; + + typedef ListHashSetReverseIterator<ListHashSet> reverse_iterator; + typedef ListHashSetConstReverseIterator<ListHashSet> const_reverse_iterator; + friend class ListHashSetReverseIterator<ListHashSet>; + friend class ListHashSetConstReverseIterator<ListHashSet>; + + template<typename ValueType> struct HashTableAddResult { + HashTableAddResult(Node* storedValue, bool isNewEntry) : storedValue(storedValue), isNewEntry(isNewEntry) { } + Node* storedValue; + bool isNewEntry; + }; + typedef HashTableAddResult<ValueType> AddResult; ListHashSet(); ListHashSet(const ListHashSet&); ListHashSet& operator=(const ListHashSet&); - ~ListHashSet(); + void finalize(); void swap(ListHashSet&); - unsigned size() const; - unsigned capacity() const; - bool isEmpty() const; - - size_t sizeInBytes() const; + unsigned size() const { return m_impl.size(); } + unsigned capacity() const { return m_impl.capacity(); } + bool isEmpty() const { return m_impl.isEmpty(); } - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; + iterator begin() { return makeIterator(m_head); } + iterator end() { return makeIterator(0); } + const_iterator begin() const { return makeConstIterator(m_head); } + const_iterator end() const { return makeConstIterator(0); } - reverse_iterator rbegin(); - reverse_iterator rend(); - const_reverse_iterator rbegin() const; - const_reverse_iterator rend() const; + reverse_iterator rbegin() { return makeReverseIterator(m_tail); } + reverse_iterator rend() { return makeReverseIterator(0); } + const_reverse_iterator rbegin() const { return makeConstReverseIterator(m_tail); } + const_reverse_iterator rend() const { return makeConstReverseIterator(0); } ValueType& first(); const ValueType& first() const; @@ -114,9 +143,9 @@ namespace WTF { const ValueType& last() const; void removeLast(); - iterator find(const ValueType&); - const_iterator find(const ValueType&) const; - bool contains(const ValueType&) const; + iterator find(ValuePeekInType); + const_iterator find(ValuePeekInType) const; + bool contains(ValuePeekInType) const; // An alternate version of find() that finds the object by hashing and comparing // with some other type, to avoid the cost of type conversion. @@ -125,24 +154,38 @@ namespace WTF { template<typename HashTranslator, typename T> const_iterator find(const T&) const; template<typename HashTranslator, typename T> bool contains(const T&) const; - // The return value of add is a pair of an iterator to the new value's location, + // The return value of add is a pair of a pointer to the stored value, // and a bool that is true if an new entry was added. - AddResult add(const ValueType&); + AddResult add(ValuePassInType); + + // Same as add() except that the return value is an + // iterator. Useful in cases where it's needed to have the + // same return value as find() and where it's not possible to + // use a pointer to the storedValue. + iterator addReturnIterator(ValuePassInType); // Add the value to the end of the collection. If the value was already in // the list, it is moved to the end. - AddResult appendOrMoveToLast(const ValueType&); + AddResult appendOrMoveToLast(ValuePassInType); // Add the value to the beginning of the collection. If the value was already in // the list, it is moved to the beginning. - AddResult prependOrMoveToFirst(const ValueType&); + AddResult prependOrMoveToFirst(ValuePassInType); - AddResult insertBefore(const ValueType& beforeValue, const ValueType& newValue); - AddResult insertBefore(iterator, const ValueType&); + AddResult insertBefore(ValuePeekInType beforeValue, ValuePassInType newValue); + AddResult insertBefore(iterator, ValuePassInType); - void remove(const ValueType&); + void remove(ValuePeekInType value) { return remove(find(value)); } void remove(iterator); void clear(); + template<typename Collection> + void removeAll(const Collection& other) { WTF::removeAll(*this, other); } + + ValuePassOutType take(iterator); + ValuePassOutType take(ValuePeekInType); + ValuePassOutType takeFirst(); + + void trace(typename Allocator::Visitor*); private: void unlink(Node*); @@ -151,42 +194,107 @@ namespace WTF { void prependNode(Node*); void insertNodeBefore(Node* beforeNode, Node* newNode); void deleteAllNodes(); - void createAllocatorIfNeeded(); + Allocator* allocator() const { return this->m_allocatorProvider.get(); } + void createAllocatorIfNeeded() { this->m_allocatorProvider.createAllocatorIfNeeded(); } + void deallocate(Node* node) const { this->m_allocatorProvider.deallocate(node); } - iterator makeIterator(Node*); - const_iterator makeConstIterator(Node*) const; - reverse_iterator makeReverseIterator(Node*); - const_reverse_iterator makeConstReverseIterator(Node*) const; - - friend void deleteAllValues<>(const ListHashSet&); + iterator makeIterator(Node* position) { return iterator(this, position); } + const_iterator makeConstIterator(Node* position) const { return const_iterator(this, position); } + reverse_iterator makeReverseIterator(Node* position) { return reverse_iterator(this, position); } + const_reverse_iterator makeConstReverseIterator(Node* position) const { return const_reverse_iterator(this, position); } ImplType m_impl; Node* m_head; Node* m_tail; - OwnPtr<NodeAllocator> m_allocator; }; - template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNodeAllocator { - typedef ListHashSetNode<ValueArg, inlineCapacity> Node; - typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator; + // ListHashSetNode has this base class to hold the members because the MSVC + // compiler otherwise gets into circular template dependencies when trying + // to do sizeof on a node. + template<typename ValueArg> class ListHashSetNodeBase { + protected: + ListHashSetNodeBase(const ValueArg& value) + : m_value(value) + , m_prev(0) + , m_next(0) +#ifndef NDEBUG + , m_isAllocated(true) +#endif + { + } + + template <typename U> + ListHashSetNodeBase(const U& value) + : m_value(value) + , m_prev(0) + , m_next(0) +#ifndef NDEBUG + , m_isAllocated(true) +#endif + { + } + + public: + ValueArg m_value; + ListHashSetNodeBase* m_prev; + ListHashSetNodeBase* m_next; +#ifndef NDEBUG + bool m_isAllocated; +#endif + }; + + // This allocator is only used for non-Heap ListHashSets. + template<typename ValueArg, size_t inlineCapacity> + struct ListHashSetAllocator : public DefaultAllocator { + typedef DefaultAllocator TableAllocator; + typedef ListHashSetNode<ValueArg, ListHashSetAllocator> Node; + typedef ListHashSetNodeBase<ValueArg> NodeBase; + class AllocatorProvider { + public: + void createAllocatorIfNeeded() + { + if (!m_allocator) + m_allocator = adoptPtr(new ListHashSetAllocator); + } + + void swap(AllocatorProvider& other) + { + m_allocator.swap(other.m_allocator); + } + + void deallocate(Node* node) const + { + ASSERT(m_allocator); + m_allocator->deallocate(node); + } + + ListHashSetAllocator* get() const + { + ASSERT(m_allocator); + return m_allocator.get(); + } - ListHashSetNodeAllocator() + private: + OwnPtr<ListHashSetAllocator> m_allocator; + }; + + ListHashSetAllocator() : m_freeList(pool()) , m_isDoneWithInitialFreeList(false) { - memset(m_pool.pool, 0, sizeof(m_pool.pool)); + memset(m_pool.buffer, 0, sizeof(m_pool.buffer)); } - Node* allocate() + Node* allocateNode() { Node* result = m_freeList; if (!result) - return static_cast<Node*>(fastMalloc(sizeof(Node))); + return static_cast<Node*>(fastMalloc(sizeof(NodeBase))); ASSERT(!result->m_isAllocated); - Node* next = result->m_next; + Node* next = result->next(); ASSERT(!next || !next->m_isAllocated); if (!next && !m_isDoneWithInitialFreeList) { next = result + 1; @@ -222,49 +330,102 @@ namespace WTF { return node >= pool() && node < pastPool(); } + static void traceValue(typename DefaultAllocator::Visitor* visitor, Node* node) { } + private: - Node* pool() { return reinterpret_cast_ptr<Node*>(m_pool.pool); } + Node* pool() { return reinterpret_cast_ptr<Node*>(m_pool.buffer); } Node* pastPool() { return pool() + m_poolSize; } Node* m_freeList; bool m_isDoneWithInitialFreeList; +#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) + // The allocation pool for nodes is one big chunk that ASAN has no + // insight into, so it can cloak errors. Make it as small as possible + // to force nodes to be allocated individually where ASAN can see them. + static const size_t m_poolSize = 1; +#else static const size_t m_poolSize = inlineCapacity; - union { - char pool[sizeof(Node) * m_poolSize]; - double forAlignment; - } m_pool; +#endif + AlignedBuffer<sizeof(NodeBase) * m_poolSize, WTF_ALIGN_OF(NodeBase)> m_pool; }; - template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNode { - typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator; + template<typename ValueArg, typename AllocatorArg> class ListHashSetNode : public ListHashSetNodeBase<ValueArg> { + public: + typedef AllocatorArg NodeAllocator; + typedef ValueArg Value; - ListHashSetNode(ValueArg value) - : m_value(value) - , m_prev(0) - , m_next(0) -#ifndef NDEBUG - , m_isAllocated(true) -#endif + template <typename U> + ListHashSetNode(U value) + : ListHashSetNodeBase<ValueArg>(value) { } + + void* operator new(size_t, NodeAllocator* allocator) { + COMPILE_ASSERT(sizeof(ListHashSetNode) == sizeof(ListHashSetNodeBase<ValueArg>), PleaseAddAnyFieldsToTheBase); + return allocator->allocateNode(); } - void* operator new(size_t, NodeAllocator* allocator) + void setWasAlreadyDestructed() { - return allocator->allocate(); + if (NodeAllocator::isGarbageCollected && HashTraits<ValueArg>::needsDestruction) + this->m_prev = unlinkedNodePointer(); } + + bool wasAlreadyDestructed() const + { + ASSERT(NodeAllocator::isGarbageCollected); + return this->m_prev == unlinkedNodePointer(); + } + + static void finalize(void* pointer) + { + ASSERT(HashTraits<ValueArg>::needsDestruction); // No need to waste time calling finalize if it's not needed. + ListHashSetNode* self = reinterpret_cast_ptr<ListHashSetNode*>(pointer); + + // Check whether this node was already destructed before being + // unlinked from the collection. + if (self->wasAlreadyDestructed()) + return; + + self->m_value.~ValueArg(); + } + void destroy(NodeAllocator* allocator) { this->~ListHashSetNode(); + setWasAlreadyDestructed(); allocator->deallocate(this); } - ValueArg m_value; - ListHashSetNode* m_prev; - ListHashSetNode* m_next; + // This is not called in normal tracing, but it is called if we find a + // pointer to a node on the stack using conservative scanning. Since + // the original ListHashSet may no longer exist we make sure to mark + // the neighbours in the chain too. + void trace(typename NodeAllocator::Visitor* visitor) + { + // The conservative stack scan can find nodes that have been + // removed from the set and destructed. We don't need to trace + // these, and it would be wrong to do so, because the class will + // not expect the trace method to be called after the destructor. + // It's an error to remove a node from the ListHashSet while an + // iterator is positioned at that node, so there should be no valid + // pointers from the stack to a destructed node. + if (wasAlreadyDestructed()) + return; + NodeAllocator::traceValue(visitor, this); + visitor->mark(next()); + visitor->mark(prev()); + } -#ifndef NDEBUG - bool m_isAllocated; -#endif + ListHashSetNode* next() const { return reinterpret_cast<ListHashSetNode*>(this->m_next); } + ListHashSetNode* prev() const { return reinterpret_cast<ListHashSetNode*>(this->m_prev); } + + // Don't add fields here, the ListHashSetNodeBase and this should have + // the same size. + + static ListHashSetNode* unlinkedNodePointer() { return reinterpret_cast<ListHashSetNode*>(-1); } + + template<typename HashArg> + friend struct ListHashSetNodeHashFunctions; }; template<typename HashArg> struct ListHashSetNodeHashFunctions { @@ -273,19 +434,15 @@ namespace WTF { static const bool safeToCompareToEmptyOrDeleted = false; }; - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetIterator { + template<typename Set> class ListHashSetIterator { private: - typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType; - typedef ListHashSetIterator<ValueArg, inlineCapacity, HashArg> iterator; - typedef ListHashSetConstIterator<ValueArg, inlineCapacity, HashArg> const_iterator; - typedef ListHashSetNode<ValueArg, inlineCapacity> Node; - typedef ValueArg ValueType; + typedef typename Set::const_iterator const_iterator; + typedef typename Set::Node Node; + typedef typename Set::ValueType ValueType; typedef ValueType& ReferenceType; typedef ValueType* PointerType; - friend class ListHashSet<ValueArg, inlineCapacity, HashArg>; - - ListHashSetIterator(const ListHashSetType* set, Node* position) : m_iterator(set, position) { } + ListHashSetIterator(const Set* set, Node* position) : m_iterator(set, position) { } public: ListHashSetIterator() { } @@ -296,17 +453,14 @@ namespace WTF { ReferenceType operator*() const { return *get(); } PointerType operator->() const { return get(); } - iterator& operator++() { ++m_iterator; return *this; } - - // postfix ++ intentionally omitted - - iterator& operator--() { --m_iterator; return *this; } + ListHashSetIterator& operator++() { ++m_iterator; return *this; } + ListHashSetIterator& operator--() { --m_iterator; return *this; } - // postfix -- intentionally omitted + // Postfix ++ and -- intentionally omitted. // Comparison. - bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; } - bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; } + bool operator==(const ListHashSetIterator& other) const { return m_iterator == other.m_iterator; } + bool operator!=(const ListHashSetIterator& other) const { return m_iterator != other.m_iterator; } operator const_iterator() const { return m_iterator; } @@ -314,22 +468,23 @@ namespace WTF { Node* node() { return m_iterator.node(); } const_iterator m_iterator; + + template<typename T, size_t inlineCapacity, typename U, typename V> + friend class ListHashSet; }; - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstIterator { + template<typename Set> + class ListHashSetConstIterator { private: - typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType; - typedef ListHashSetIterator<ValueArg, inlineCapacity, HashArg> iterator; - typedef ListHashSetConstIterator<ValueArg, inlineCapacity, HashArg> const_iterator; - typedef ListHashSetNode<ValueArg, inlineCapacity> Node; - typedef ValueArg ValueType; + typedef typename Set::const_iterator const_iterator; + typedef typename Set::Node Node; + typedef typename Set::ValueType ValueType; typedef const ValueType& ReferenceType; typedef const ValueType* PointerType; - friend class ListHashSet<ValueArg, inlineCapacity, HashArg>; - friend class ListHashSetIterator<ValueArg, inlineCapacity, HashArg>; + friend class ListHashSetIterator<Set>; - ListHashSetConstIterator(const ListHashSetType* set, Node* position) + ListHashSetConstIterator(const Set* set, Node* position) : m_set(set) , m_position(position) { @@ -347,33 +502,31 @@ namespace WTF { ReferenceType operator*() const { return *get(); } PointerType operator->() const { return get(); } - const_iterator& operator++() + ListHashSetConstIterator& operator++() { ASSERT(m_position != 0); - m_position = m_position->m_next; + m_position = m_position->next(); return *this; } - // postfix ++ intentionally omitted - - const_iterator& operator--() + ListHashSetConstIterator& operator--() { ASSERT(m_position != m_set->m_head); if (!m_position) m_position = m_set->m_tail; else - m_position = m_position->m_prev; + m_position = m_position->prev(); return *this; } - // postfix -- intentionally omitted + // Postfix ++ and -- intentionally omitted. // Comparison. - bool operator==(const const_iterator& other) const + bool operator==(const ListHashSetConstIterator& other) const { return m_position == other.m_position; } - bool operator!=(const const_iterator& other) const + bool operator!=(const ListHashSetConstIterator& other) const { return m_position != other.m_position; } @@ -381,23 +534,23 @@ namespace WTF { private: Node* node() { return m_position; } - const ListHashSetType* m_set; + const Set* m_set; Node* m_position; + + template<typename T, size_t inlineCapacity, typename U, typename V> + friend class ListHashSet; }; - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetReverseIterator { + template<typename Set> + class ListHashSetReverseIterator { private: - typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType; - typedef ListHashSetReverseIterator<ValueArg, inlineCapacity, HashArg> reverse_iterator; - typedef ListHashSetConstReverseIterator<ValueArg, inlineCapacity, HashArg> const_reverse_iterator; - typedef ListHashSetNode<ValueArg, inlineCapacity> Node; - typedef ValueArg ValueType; + typedef typename Set::const_reverse_iterator const_reverse_iterator; + typedef typename Set::Node Node; + typedef typename Set::ValueType ValueType; typedef ValueType& ReferenceType; typedef ValueType* PointerType; - friend class ListHashSet<ValueArg, inlineCapacity, HashArg>; - - ListHashSetReverseIterator(const ListHashSetType* set, Node* position) : m_iterator(set, position) { } + ListHashSetReverseIterator(const Set* set, Node* position) : m_iterator(set, position) { } public: ListHashSetReverseIterator() { } @@ -408,17 +561,14 @@ namespace WTF { ReferenceType operator*() const { return *get(); } PointerType operator->() const { return get(); } - reverse_iterator& operator++() { ++m_iterator; return *this; } - - // postfix ++ intentionally omitted - - reverse_iterator& operator--() { --m_iterator; return *this; } + ListHashSetReverseIterator& operator++() { ++m_iterator; return *this; } + ListHashSetReverseIterator& operator--() { --m_iterator; return *this; } - // postfix -- intentionally omitted + // Postfix ++ and -- intentionally omitted. // Comparison. - bool operator==(const reverse_iterator& other) const { return m_iterator == other.m_iterator; } - bool operator!=(const reverse_iterator& other) const { return m_iterator != other.m_iterator; } + bool operator==(const ListHashSetReverseIterator& other) const { return m_iterator == other.m_iterator; } + bool operator!=(const ListHashSetReverseIterator& other) const { return m_iterator != other.m_iterator; } operator const_reverse_iterator() const { return m_iterator; } @@ -426,22 +576,22 @@ namespace WTF { Node* node() { return m_iterator.node(); } const_reverse_iterator m_iterator; + + template<typename T, size_t inlineCapacity, typename U, typename V> + friend class ListHashSet; }; - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstReverseIterator { + template<typename Set> class ListHashSetConstReverseIterator { private: - typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType; - typedef ListHashSetReverseIterator<ValueArg, inlineCapacity, HashArg> reverse_iterator; - typedef ListHashSetConstReverseIterator<ValueArg, inlineCapacity, HashArg> const_reverse_iterator; - typedef ListHashSetNode<ValueArg, inlineCapacity> Node; - typedef ValueArg ValueType; + typedef typename Set::reverse_iterator reverse_iterator; + typedef typename Set::Node Node; + typedef typename Set::ValueType ValueType; typedef const ValueType& ReferenceType; typedef const ValueType* PointerType; - friend class ListHashSet<ValueArg, inlineCapacity, HashArg>; - friend class ListHashSetReverseIterator<ValueArg, inlineCapacity, HashArg>; + friend class ListHashSetReverseIterator<Set>; - ListHashSetConstReverseIterator(const ListHashSetType* set, Node* position) + ListHashSetConstReverseIterator(const Set* set, Node* position) : m_set(set) , m_position(position) { @@ -459,33 +609,31 @@ namespace WTF { ReferenceType operator*() const { return *get(); } PointerType operator->() const { return get(); } - const_reverse_iterator& operator++() + ListHashSetConstReverseIterator& operator++() { ASSERT(m_position != 0); - m_position = m_position->m_prev; + m_position = m_position->prev(); return *this; } - // postfix ++ intentionally omitted - - const_reverse_iterator& operator--() + ListHashSetConstReverseIterator& operator--() { ASSERT(m_position != m_set->m_tail); if (!m_position) m_position = m_set->m_head; else - m_position = m_position->m_next; + m_position = m_position->next(); return *this; } - // postfix -- intentionally omitted + // Postfix ++ and -- intentionally omitted. // Comparison. - bool operator==(const const_reverse_iterator& other) const + bool operator==(const ListHashSetConstReverseIterator& other) const { return m_position == other.m_position; } - bool operator!=(const const_reverse_iterator& other) const + bool operator!=(const ListHashSetConstReverseIterator& other) const { return m_position != other.m_position; } @@ -493,8 +641,11 @@ namespace WTF { private: Node* node() { return m_position; } - const ListHashSetType* m_set; + const Set* m_set; Node* m_position; + + template<typename T, size_t inlineCapacity, typename U, typename V> + friend class ListHashSet; }; template<typename HashFunctions> @@ -503,19 +654,19 @@ namespace WTF { template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a->m_value, b); } template<typename T, typename U, typename V> static void translate(T*& location, const U& key, const V& allocator) { - location = new (allocator) T(key); + location = new (const_cast<V*>(&allocator)) T(key); } }; - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSet<T, inlineCapacity, U>::ListHashSet() + template<typename T, size_t inlineCapacity, typename U, typename V> + inline ListHashSet<T, inlineCapacity, U, V>::ListHashSet() : m_head(0) , m_tail(0) { } - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSet<T, inlineCapacity, U>::ListHashSet(const ListHashSet& other) + template<typename T, size_t inlineCapacity, typename U, typename V> + inline ListHashSet<T, inlineCapacity, U, V>::ListHashSet(const ListHashSet& other) : m_head(0) , m_tail(0) { @@ -524,155 +675,76 @@ namespace WTF { add(*it); } - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSet<T, inlineCapacity, U>& ListHashSet<T, inlineCapacity, U>::operator=(const ListHashSet& other) + template<typename T, size_t inlineCapacity, typename U, typename V> + inline ListHashSet<T, inlineCapacity, U, V>& ListHashSet<T, inlineCapacity, U, V>::operator=(const ListHashSet& other) { ListHashSet tmp(other); swap(tmp); return *this; } - template<typename T, size_t inlineCapacity, typename U> - inline void ListHashSet<T, inlineCapacity, U>::swap(ListHashSet& other) + template<typename T, size_t inlineCapacity, typename U, typename V> + inline void ListHashSet<T, inlineCapacity, U, V>::swap(ListHashSet& other) { m_impl.swap(other.m_impl); std::swap(m_head, other.m_head); std::swap(m_tail, other.m_tail); - m_allocator.swap(other.m_allocator); + this->m_allocatorProvider.swap(other.m_allocatorProvider); } - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSet<T, inlineCapacity, U>::~ListHashSet() + template<typename T, size_t inlineCapacity, typename U, typename V> + inline void ListHashSet<T, inlineCapacity, U, V>::finalize() { + COMPILE_ASSERT(!Allocator::isGarbageCollected, FinalizeOnHeapAllocatedListHashSetShouldNeverBeCalled); deleteAllNodes(); } - template<typename T, size_t inlineCapacity, typename U> - inline unsigned ListHashSet<T, inlineCapacity, U>::size() const - { - return m_impl.size(); - } - - template<typename T, size_t inlineCapacity, typename U> - inline unsigned ListHashSet<T, inlineCapacity, U>::capacity() const - { - return m_impl.capacity(); - } - - template<typename T, size_t inlineCapacity, typename U> - inline bool ListHashSet<T, inlineCapacity, U>::isEmpty() const - { - return m_impl.isEmpty(); - } - - template<typename T, size_t inlineCapacity, typename U> - size_t ListHashSet<T, inlineCapacity, U>::sizeInBytes() const - { - size_t result = sizeof(*this); - if (!m_allocator) - return result; - result += sizeof(*m_allocator) + (sizeof(typename ImplType::ValueType) * m_impl.capacity()); - for (Node* node = m_head; node; node = node->m_next) { - if (!m_allocator->inPool(node)) - result += sizeof(Node); - } - return result; - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::begin() - { - return makeIterator(m_head); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::end() - { - return makeIterator(0); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::const_iterator ListHashSet<T, inlineCapacity, U>::begin() const - { - return makeConstIterator(m_head); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::const_iterator ListHashSet<T, inlineCapacity, U>::end() const - { - return makeConstIterator(0); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::reverse_iterator ListHashSet<T, inlineCapacity, U>::rbegin() - { - return makeReverseIterator(m_tail); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::reverse_iterator ListHashSet<T, inlineCapacity, U>::rend() - { - return makeReverseIterator(0); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::const_reverse_iterator ListHashSet<T, inlineCapacity, U>::rbegin() const - { - return makeConstReverseIterator(m_tail); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::const_reverse_iterator ListHashSet<T, inlineCapacity, U>::rend() const - { - return makeConstReverseIterator(0); - } - - template<typename T, size_t inlineCapacity, typename U> - inline T& ListHashSet<T, inlineCapacity, U>::first() + template<typename T, size_t inlineCapacity, typename U, typename V> + inline T& ListHashSet<T, inlineCapacity, U, V>::first() { ASSERT(!isEmpty()); return m_head->m_value; } - template<typename T, size_t inlineCapacity, typename U> - inline void ListHashSet<T, inlineCapacity, U>::removeFirst() + template<typename T, size_t inlineCapacity, typename U, typename V> + inline void ListHashSet<T, inlineCapacity, U, V>::removeFirst() { ASSERT(!isEmpty()); m_impl.remove(m_head); unlinkAndDelete(m_head); } - template<typename T, size_t inlineCapacity, typename U> - inline const T& ListHashSet<T, inlineCapacity, U>::first() const + template<typename T, size_t inlineCapacity, typename U, typename V> + inline const T& ListHashSet<T, inlineCapacity, U, V>::first() const { ASSERT(!isEmpty()); return m_head->m_value; } - template<typename T, size_t inlineCapacity, typename U> - inline T& ListHashSet<T, inlineCapacity, U>::last() + template<typename T, size_t inlineCapacity, typename U, typename V> + inline T& ListHashSet<T, inlineCapacity, U, V>::last() { ASSERT(!isEmpty()); return m_tail->m_value; } - template<typename T, size_t inlineCapacity, typename U> - inline const T& ListHashSet<T, inlineCapacity, U>::last() const + template<typename T, size_t inlineCapacity, typename U, typename V> + inline const T& ListHashSet<T, inlineCapacity, U, V>::last() const { ASSERT(!isEmpty()); return m_tail->m_value; } - template<typename T, size_t inlineCapacity, typename U> - inline void ListHashSet<T, inlineCapacity, U>::removeLast() + template<typename T, size_t inlineCapacity, typename U, typename V> + inline void ListHashSet<T, inlineCapacity, U, V>::removeLast() { ASSERT(!isEmpty()); m_impl.remove(m_tail); unlinkAndDelete(m_tail); } - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::find(const ValueType& value) + template<typename T, size_t inlineCapacity, typename U, typename V> + inline typename ListHashSet<T, inlineCapacity, U, V>::iterator ListHashSet<T, inlineCapacity, U, V>::find(ValuePeekInType value) { ImplTypeIterator it = m_impl.template find<BaseTranslator>(value); if (it == m_impl.end()) @@ -680,8 +752,8 @@ namespace WTF { return makeIterator(*it); } - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::const_iterator ListHashSet<T, inlineCapacity, U>::find(const ValueType& value) const + template<typename T, size_t inlineCapacity, typename U, typename V> + inline typename ListHashSet<T, inlineCapacity, U, V>::const_iterator ListHashSet<T, inlineCapacity, U, V>::find(ValuePeekInType value) const { ImplTypeConstIterator it = m_impl.template find<BaseTranslator>(value); if (it == m_impl.end()) @@ -695,9 +767,9 @@ namespace WTF { template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a->m_value, b); } }; - template<typename ValueType, size_t inlineCapacity, typename U> + template<typename ValueType, size_t inlineCapacity, typename U, typename V> template<typename HashTranslator, typename T> - inline typename ListHashSet<ValueType, inlineCapacity, U>::iterator ListHashSet<ValueType, inlineCapacity, U>::find(const T& value) + inline typename ListHashSet<ValueType, inlineCapacity, U, V>::iterator ListHashSet<ValueType, inlineCapacity, U, V>::find(const T& value) { ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator> >(value); if (it == m_impl.end()) @@ -705,9 +777,9 @@ namespace WTF { return makeIterator(*it); } - template<typename ValueType, size_t inlineCapacity, typename U> + template<typename ValueType, size_t inlineCapacity, typename U, typename V> template<typename HashTranslator, typename T> - inline typename ListHashSet<ValueType, inlineCapacity, U>::const_iterator ListHashSet<ValueType, inlineCapacity, U>::find(const T& value) const + inline typename ListHashSet<ValueType, inlineCapacity, U, V>::const_iterator ListHashSet<ValueType, inlineCapacity, U, V>::find(const T& value) const { ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator> >(value); if (it == m_impl.end()) @@ -715,72 +787,82 @@ namespace WTF { return makeConstIterator(*it); } - template<typename ValueType, size_t inlineCapacity, typename U> + template<typename ValueType, size_t inlineCapacity, typename U, typename V> template<typename HashTranslator, typename T> - inline bool ListHashSet<ValueType, inlineCapacity, U>::contains(const T& value) const + inline bool ListHashSet<ValueType, inlineCapacity, U, V>::contains(const T& value) const { return m_impl.template contains<ListHashSetTranslatorAdapter<HashTranslator> >(value); } - template<typename T, size_t inlineCapacity, typename U> - inline bool ListHashSet<T, inlineCapacity, U>::contains(const ValueType& value) const + template<typename T, size_t inlineCapacity, typename U, typename V> + inline bool ListHashSet<T, inlineCapacity, U, V>::contains(ValuePeekInType value) const { return m_impl.template contains<BaseTranslator>(value); } - template<typename T, size_t inlineCapacity, typename U> - typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::add(const ValueType &value) + template<typename T, size_t inlineCapacity, typename U, typename V> + typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::add(ValuePassInType value) { createAllocatorIfNeeded(); - typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(value, m_allocator.get()); + // The second argument is a const ref. This is useful for the HashTable + // because it lets it take lvalues by reference, but for our purposes + // it's inconvenient, since it constrains us to be const, whereas the + // allocator actually changes when it does allocations. + typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(value, *this->allocator()); if (result.isNewEntry) - appendNode(*result.iterator); - return AddResult(makeIterator(*result.iterator), result.isNewEntry); + appendNode(*result.storedValue); + return AddResult(*result.storedValue, result.isNewEntry); + } + + template<typename T, size_t inlineCapacity, typename U, typename V> + typename ListHashSet<T, inlineCapacity, U, V>::iterator ListHashSet<T, inlineCapacity, U, V>::addReturnIterator(ValuePassInType value) + { + return makeIterator(add(value).storedValue); } - template<typename T, size_t inlineCapacity, typename U> - typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::appendOrMoveToLast(const ValueType &value) + template<typename T, size_t inlineCapacity, typename U, typename V> + typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::appendOrMoveToLast(ValuePassInType value) { createAllocatorIfNeeded(); - typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(value, m_allocator.get()); - Node* node = *result.iterator; + typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(value, *this->allocator()); + Node* node = *result.storedValue; if (!result.isNewEntry) unlink(node); appendNode(node); - return AddResult(makeIterator(*result.iterator), result.isNewEntry); + return AddResult(*result.storedValue, result.isNewEntry); } - template<typename T, size_t inlineCapacity, typename U> - typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::prependOrMoveToFirst(const ValueType &value) + template<typename T, size_t inlineCapacity, typename U, typename V> + typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::prependOrMoveToFirst(ValuePassInType value) { createAllocatorIfNeeded(); - typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(value, m_allocator.get()); - Node* node = *result.iterator; + typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(value, *this->allocator()); + Node* node = *result.storedValue; if (!result.isNewEntry) unlink(node); prependNode(node); - return AddResult(makeIterator(*result.iterator), result.isNewEntry); + return AddResult(*result.storedValue, result.isNewEntry); } - template<typename T, size_t inlineCapacity, typename U> - typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::insertBefore(iterator it, const ValueType& newValue) + template<typename T, size_t inlineCapacity, typename U, typename V> + typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::insertBefore(iterator it, ValuePassInType newValue) { createAllocatorIfNeeded(); - typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(newValue, m_allocator.get()); + typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(newValue, *this->allocator()); if (result.isNewEntry) - insertNodeBefore(it.node(), *result.iterator); - return AddResult(makeIterator(*result.iterator), result.isNewEntry); + insertNodeBefore(it.node(), *result.storedValue); + return AddResult(*result.storedValue, result.isNewEntry); } - template<typename T, size_t inlineCapacity, typename U> - typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::insertBefore(const ValueType& beforeValue, const ValueType& newValue) + template<typename T, size_t inlineCapacity, typename U, typename V> + typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::insertBefore(ValuePeekInType beforeValue, ValuePassInType newValue) { createAllocatorIfNeeded(); return insertBefore(find(beforeValue), newValue); } - template<typename T, size_t inlineCapacity, typename U> - inline void ListHashSet<T, inlineCapacity, U>::remove(iterator it) + template<typename T, size_t inlineCapacity, typename U, typename V> + inline void ListHashSet<T, inlineCapacity, U, V>::remove(iterator it) { if (it == end()) return; @@ -788,14 +870,8 @@ namespace WTF { unlinkAndDelete(it.node()); } - template<typename T, size_t inlineCapacity, typename U> - inline void ListHashSet<T, inlineCapacity, U>::remove(const ValueType& value) - { - remove(find(value)); - } - - template<typename T, size_t inlineCapacity, typename U> - inline void ListHashSet<T, inlineCapacity, U>::clear() + template<typename T, size_t inlineCapacity, typename U, typename V> + inline void ListHashSet<T, inlineCapacity, U, V>::clear() { deleteAllNodes(); m_impl.clear(); @@ -803,12 +879,42 @@ namespace WTF { m_tail = 0; } - template<typename T, size_t inlineCapacity, typename U> - void ListHashSet<T, inlineCapacity, U>::unlink(Node* node) + template<typename T, size_t inlineCapacity, typename U, typename V> + typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType ListHashSet<T, inlineCapacity, U, V>::take(iterator it) + { + if (it == end()) + return ValueTraits::emptyValue(); + + m_impl.remove(it.node()); + ValuePassOutType result = ValueTraits::passOut(it.node()->m_value); + unlinkAndDelete(it.node()); + + return result; + } + + template<typename T, size_t inlineCapacity, typename U, typename V> + typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType ListHashSet<T, inlineCapacity, U, V>::take(ValuePeekInType value) + { + return take(find(value)); + } + + template<typename T, size_t inlineCapacity, typename U, typename V> + typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType ListHashSet<T, inlineCapacity, U, V>::takeFirst() + { + ASSERT(!isEmpty()); + m_impl.remove(m_head); + ValuePassOutType result = ValueTraits::passOut(m_head->m_value); + unlinkAndDelete(m_head); + + return result; + } + + template<typename T, size_t inlineCapacity, typename U, typename Allocator> + void ListHashSet<T, inlineCapacity, U, Allocator>::unlink(Node* node) { if (!node->m_prev) { ASSERT(node == m_head); - m_head = node->m_next; + m_head = node->next(); } else { ASSERT(node != m_head); node->m_prev->m_next = node->m_next; @@ -816,22 +922,22 @@ namespace WTF { if (!node->m_next) { ASSERT(node == m_tail); - m_tail = node->m_prev; + m_tail = node->prev(); } else { ASSERT(node != m_tail); node->m_next->m_prev = node->m_prev; } } - template<typename T, size_t inlineCapacity, typename U> - void ListHashSet<T, inlineCapacity, U>::unlinkAndDelete(Node* node) + template<typename T, size_t inlineCapacity, typename U, typename V> + void ListHashSet<T, inlineCapacity, U, V>::unlinkAndDelete(Node* node) { unlink(node); - node->destroy(m_allocator.get()); + node->destroy(this->allocator()); } - template<typename T, size_t inlineCapacity, typename U> - void ListHashSet<T, inlineCapacity, U>::appendNode(Node* node) + template<typename T, size_t inlineCapacity, typename U, typename V> + void ListHashSet<T, inlineCapacity, U, V>::appendNode(Node* node) { node->m_prev = m_tail; node->m_next = 0; @@ -847,8 +953,8 @@ namespace WTF { m_tail = node; } - template<typename T, size_t inlineCapacity, typename U> - void ListHashSet<T, inlineCapacity, U>::prependNode(Node* node) + template<typename T, size_t inlineCapacity, typename U, typename V> + void ListHashSet<T, inlineCapacity, U, V>::prependNode(Node* node) { node->m_prev = 0; node->m_next = m_head; @@ -861,8 +967,8 @@ namespace WTF { m_head = node; } - template<typename T, size_t inlineCapacity, typename U> - void ListHashSet<T, inlineCapacity, U>::insertNodeBefore(Node* beforeNode, Node* newNode) + template<typename T, size_t inlineCapacity, typename U, typename V> + void ListHashSet<T, inlineCapacity, U, V>::insertNodeBefore(Node* beforeNode, Node* newNode) { if (!beforeNode) return appendNode(newNode); @@ -877,59 +983,24 @@ namespace WTF { m_head = newNode; } - template<typename T, size_t inlineCapacity, typename U> - void ListHashSet<T, inlineCapacity, U>::deleteAllNodes() + template<typename T, size_t inlineCapacity, typename U, typename V> + void ListHashSet<T, inlineCapacity, U, V>::deleteAllNodes() { if (!m_head) return; - for (Node* node = m_head, *next = m_head->m_next; node; node = next, next = node ? node->m_next : 0) - node->destroy(m_allocator.get()); - } - - template<typename T, size_t inlineCapacity, typename U> - void ListHashSet<T, inlineCapacity, U>::createAllocatorIfNeeded() - { - if (!m_allocator) - m_allocator = adoptPtr(new NodeAllocator); - } - - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSetReverseIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeReverseIterator(Node* position) - { - return ListHashSetReverseIterator<T, inlineCapacity, U>(this, position); - } - - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSetConstReverseIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeConstReverseIterator(Node* position) const - { - return ListHashSetConstReverseIterator<T, inlineCapacity, U>(this, position); - } - - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSetIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeIterator(Node* position) - { - return ListHashSetIterator<T, inlineCapacity, U>(this, position); - } - - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSetConstIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeConstIterator(Node* position) const - { - return ListHashSetConstIterator<T, inlineCapacity, U>(this, position); - } - template<bool, typename ValueType, typename HashTableType> - void deleteAllValues(HashTableType& collection) - { - typedef typename HashTableType::const_iterator iterator; - iterator end = collection.end(); - for (iterator it = collection.begin(); it != end; ++it) - delete (*it)->m_value; + for (Node* node = m_head, *next = m_head->next(); node; node = next, next = node ? node->next() : 0) + node->destroy(this->allocator()); } - template<typename T, size_t inlineCapacity, typename U> - inline void deleteAllValues(const ListHashSet<T, inlineCapacity, U>& collection) + template<typename T, size_t inlineCapacity, typename U, typename V> + void ListHashSet<T, inlineCapacity, U, V>::trace(typename Allocator::Visitor* visitor) { - deleteAllValues<true, typename ListHashSet<T, inlineCapacity, U>::ValueType>(collection.m_impl); + COMPILE_ASSERT(HashTraits<T>::weakHandlingFlag == NoWeakHandlingInCollections, ListHashSetDoesNotSupportWeakness); + // This marks all the nodes and their contents live that can be + // accessed through the HashTable. That includes m_head and m_tail + // so we do not have to explicitly trace them here. + m_impl.trace(visitor); } } // namespace WTF |