| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2009 Google Inc. All rights reserved. | 3 * Copyright (C) 2009 Google Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * | 8 * |
| 9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 | 32 |
| 33 // FIXME: Could move what Vector and Deque share into a separate file. | 33 // FIXME: Could move what Vector and Deque share into a separate file. |
| 34 // Deque doesn't actually use Vector. | 34 // Deque doesn't actually use Vector. |
| 35 | 35 |
| 36 #include "wtf/PassTraits.h" | 36 #include "wtf/PassTraits.h" |
| 37 #include "wtf/Vector.h" | 37 #include "wtf/Vector.h" |
| 38 #include <iterator> | 38 #include <iterator> |
| 39 | 39 |
| 40 namespace WTF { | 40 namespace WTF { |
| 41 | 41 |
| 42 template <typename T, size_t inlineCapacity, typename Allocator> class DequeIter
atorBase; | 42 template <typename T, size_t inlineCapacity, typename Allocator> |
| 43 template <typename T, size_t inlineCapacity, typename Allocator> class DequeIter
ator; | 43 class DequeIteratorBase; |
| 44 template <typename T, size_t inlineCapacity, typename Allocator> class DequeCons
tIterator; | 44 template <typename T, size_t inlineCapacity, typename Allocator> |
| 45 class DequeIterator; |
| 46 template <typename T, size_t inlineCapacity, typename Allocator> |
| 47 class DequeConstIterator; |
| 45 | 48 |
| 46 template <typename T, size_t inlineCapacity = 0, typename Allocator = PartitionA
llocator> | 49 template <typename T, size_t inlineCapacity = 0, typename Allocator = PartitionA
llocator> |
| 47 class Deque : public ConditionalDestructor<Deque<T, INLINE_CAPACITY, Allocator>,
(INLINE_CAPACITY == 0) && Allocator::isGarbageCollected> { | 50 class Deque : public ConditionalDestructor<Deque<T, INLINE_CAPACITY, Allocator>,
(INLINE_CAPACITY == 0) && Allocator::isGarbageCollected> { |
| 48 WTF_USE_ALLOCATOR(Deque, Allocator); | 51 WTF_USE_ALLOCATOR(Deque, Allocator); |
| 49 public: | 52 |
| 50 typedef DequeIterator<T, inlineCapacity, Allocator> iterator; | 53 public: |
| 51 typedef DequeConstIterator<T, inlineCapacity, Allocator> const_iterator; | 54 typedef DequeIterator<T, inlineCapacity, Allocator> iterator; |
| 52 typedef std::reverse_iterator<iterator> reverse_iterator; | 55 typedef DequeConstIterator<T, inlineCapacity, Allocator> const_iterator; |
| 53 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; | 56 typedef std::reverse_iterator<iterator> reverse_iterator; |
| 54 typedef PassTraits<T> Pass; | 57 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
| 55 typedef typename PassTraits<T>::PassType PassType; | 58 typedef PassTraits<T> Pass; |
| 56 | 59 typedef typename PassTraits<T>::PassType PassType; |
| 57 Deque(); | 60 |
| 58 Deque(const Deque<T, inlineCapacity, Allocator>&); | 61 Deque(); |
| 59 // FIXME: Doesn't work if there is an inline buffer, due to crbug.com/360572 | 62 Deque(const Deque<T, inlineCapacity, Allocator>&); |
| 60 Deque<T, 0, Allocator>& operator=(const Deque&); | 63 // FIXME: Doesn't work if there is an inline buffer, due to crbug.com/360572 |
| 61 | 64 Deque<T, 0, Allocator>& operator=(const Deque&); |
| 62 void finalize(); | 65 |
| 63 void finalizeGarbageCollectedObject() { finalize(); } | 66 void finalize(); |
| 64 | 67 void finalizeGarbageCollectedObject() { finalize(); } |
| 65 // We hard wire the inlineCapacity to zero here, due to crbug.com/360572 | 68 |
| 66 void swap(Deque<T, 0, Allocator>&); | 69 // We hard wire the inlineCapacity to zero here, due to crbug.com/360572 |
| 67 | 70 void swap(Deque<T, 0, Allocator>&); |
| 68 size_t size() const { return m_start <= m_end ? m_end - m_start : m_end + m_
buffer.capacity() - m_start; } | 71 |
| 69 bool isEmpty() const { return m_start == m_end; } | 72 size_t size() const { return m_start <= m_end ? m_end - m_start : m_end + m_bu
ffer.capacity() - m_start; } |
| 70 | 73 bool isEmpty() const { return m_start == m_end; } |
| 71 iterator begin() { return iterator(this, m_start); } | 74 |
| 72 iterator end() { return iterator(this, m_end); } | 75 iterator begin() { return iterator(this, m_start); } |
| 73 const_iterator begin() const { return const_iterator(this, m_start); } | 76 iterator end() { return iterator(this, m_end); } |
| 74 const_iterator end() const { return const_iterator(this, m_end); } | 77 const_iterator begin() const { return const_iterator(this, m_start); } |
| 75 reverse_iterator rbegin() { return reverse_iterator(end()); } | 78 const_iterator end() const { return const_iterator(this, m_end); } |
| 76 reverse_iterator rend() { return reverse_iterator(begin()); } | 79 reverse_iterator rbegin() { return reverse_iterator(end()); } |
| 77 const_reverse_iterator rbegin() const { return const_reverse_iterator(end())
; } | 80 reverse_iterator rend() { return reverse_iterator(begin()); } |
| 78 const_reverse_iterator rend() const { return const_reverse_iterator(begin())
; } | 81 const_reverse_iterator rbegin() const { return const_reverse_iterator(end());
} |
| 79 | 82 const_reverse_iterator rend() const { return const_reverse_iterator(begin());
} |
| 80 T& first() { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; } | 83 |
| 81 const T& first() const { ASSERT(m_start != m_end); return m_buffer.buffer()[
m_start]; } | 84 T& first() { |
| 82 PassType takeFirst(); | 85 ASSERT(m_start != m_end); |
| 83 | 86 return m_buffer.buffer()[m_start]; |
| 84 T& last() { ASSERT(m_start != m_end); return *(--end()); } | 87 } |
| 85 const T& last() const { ASSERT(m_start != m_end); return *(--end()); } | 88 const T& first() const { |
| 86 PassType takeLast(); | 89 ASSERT(m_start != m_end); |
| 87 | 90 return m_buffer.buffer()[m_start]; |
| 88 T& at(size_t i) | 91 } |
| 89 { | 92 PassType takeFirst(); |
| 90 RELEASE_ASSERT(i < size()); | 93 |
| 91 size_t right = m_buffer.capacity() - m_start; | 94 T& last() { |
| 92 return i < right ? m_buffer.buffer()[m_start + i] : m_buffer.buffer()[i
- right]; | 95 ASSERT(m_start != m_end); |
| 93 } | 96 return *(--end()); |
| 94 const T& at(size_t i) const | 97 } |
| 95 { | 98 const T& last() const { |
| 96 RELEASE_ASSERT(i < size()); | 99 ASSERT(m_start != m_end); |
| 97 size_t right = m_buffer.capacity() - m_start; | 100 return *(--end()); |
| 98 return i < right ? m_buffer.buffer()[m_start + i] : m_buffer.buffer()[i
- right]; | 101 } |
| 99 } | 102 PassType takeLast(); |
| 100 | 103 |
| 101 T& operator[](size_t i) { return at(i); } | 104 T& at(size_t i) { |
| 102 const T& operator[](size_t i) const { return at(i); } | 105 RELEASE_ASSERT(i < size()); |
| 103 | 106 size_t right = m_buffer.capacity() - m_start; |
| 104 template <typename U> void append(const U&); | 107 return i < right ? m_buffer.buffer()[m_start + i] : m_buffer.buffer()[i - ri
ght]; |
| 105 template <typename U> void prepend(const U&); | 108 } |
| 106 void removeFirst(); | 109 const T& at(size_t i) const { |
| 107 void removeLast(); | 110 RELEASE_ASSERT(i < size()); |
| 108 void remove(iterator&); | 111 size_t right = m_buffer.capacity() - m_start; |
| 109 void remove(const_iterator&); | 112 return i < right ? m_buffer.buffer()[m_start + i] : m_buffer.buffer()[i - ri
ght]; |
| 110 | 113 } |
| 111 void clear(); | 114 |
| 112 | 115 T& operator[](size_t i) { return at(i); } |
| 113 template <typename Predicate> | 116 const T& operator[](size_t i) const { return at(i); } |
| 114 iterator findIf(Predicate&); | 117 |
| 115 | 118 template <typename U> |
| 116 template <typename VisitorDispatcher> void trace(VisitorDispatcher); | 119 void append(const U&); |
| 117 | 120 template <typename U> |
| 118 private: | 121 void prepend(const U&); |
| 119 friend class DequeIteratorBase<T, inlineCapacity, Allocator>; | 122 void removeFirst(); |
| 120 | 123 void removeLast(); |
| 121 typedef VectorBuffer<T, INLINE_CAPACITY, Allocator> Buffer; | 124 void remove(iterator&); |
| 122 typedef VectorTypeOperations<T> TypeOperations; | 125 void remove(const_iterator&); |
| 123 typedef DequeIteratorBase<T, inlineCapacity, Allocator> IteratorBase; | 126 |
| 124 | 127 void clear(); |
| 125 void remove(size_t position); | 128 |
| 126 void destroyAll(); | 129 template <typename Predicate> |
| 127 void expandCapacityIfNeeded(); | 130 iterator findIf(Predicate&); |
| 128 void expandCapacity(); | 131 |
| 129 | 132 template <typename VisitorDispatcher> |
| 130 Buffer m_buffer; | 133 void trace(VisitorDispatcher); |
| 131 unsigned m_start; | 134 |
| 132 unsigned m_end; | 135 private: |
| 136 friend class DequeIteratorBase<T, inlineCapacity, Allocator>; |
| 137 |
| 138 typedef VectorBuffer<T, INLINE_CAPACITY, Allocator> Buffer; |
| 139 typedef VectorTypeOperations<T> TypeOperations; |
| 140 typedef DequeIteratorBase<T, inlineCapacity, Allocator> IteratorBase; |
| 141 |
| 142 void remove(size_t position); |
| 143 void destroyAll(); |
| 144 void expandCapacityIfNeeded(); |
| 145 void expandCapacity(); |
| 146 |
| 147 Buffer m_buffer; |
| 148 unsigned m_start; |
| 149 unsigned m_end; |
| 133 }; | 150 }; |
| 134 | 151 |
| 135 template <typename T, size_t inlineCapacity, typename Allocator> | 152 template <typename T, size_t inlineCapacity, typename Allocator> |
| 136 class DequeIteratorBase { | 153 class DequeIteratorBase { |
| 137 protected: | 154 protected: |
| 138 DequeIteratorBase(); | 155 DequeIteratorBase(); |
| 139 DequeIteratorBase(const Deque<T, inlineCapacity, Allocator>*, size_t); | 156 DequeIteratorBase(const Deque<T, inlineCapacity, Allocator>*, size_t); |
| 140 DequeIteratorBase(const DequeIteratorBase&); | 157 DequeIteratorBase(const DequeIteratorBase&); |
| 141 DequeIteratorBase<T, 0, Allocator>& operator=(const DequeIteratorBase<T, 0,
Allocator>&); | 158 DequeIteratorBase<T, 0, Allocator>& operator=(const DequeIteratorBase<T, 0, Al
locator>&); |
| 142 ~DequeIteratorBase(); | 159 ~DequeIteratorBase(); |
| 143 | 160 |
| 144 void assign(const DequeIteratorBase& other) { *this = other; } | 161 void assign(const DequeIteratorBase& other) { *this = other; } |
| 145 | 162 |
| 146 void increment(); | 163 void increment(); |
| 147 void decrement(); | 164 void decrement(); |
| 148 | 165 |
| 149 T* before() const; | 166 T* before() const; |
| 150 T* after() const; | 167 T* after() const; |
| 151 | 168 |
| 152 bool isEqual(const DequeIteratorBase&) const; | 169 bool isEqual(const DequeIteratorBase&) const; |
| 153 | 170 |
| 154 private: | 171 private: |
| 155 Deque<T, inlineCapacity, Allocator>* m_deque; | 172 Deque<T, inlineCapacity, Allocator>* m_deque; |
| 156 unsigned m_index; | 173 unsigned m_index; |
| 157 | 174 |
| 158 friend class Deque<T, inlineCapacity, Allocator>; | 175 friend class Deque<T, inlineCapacity, Allocator>; |
| 159 }; | 176 }; |
| 160 | 177 |
| 161 template <typename T, size_t inlineCapacity = 0, typename Allocator = PartitionA
llocator> | 178 template <typename T, size_t inlineCapacity = 0, typename Allocator = PartitionA
llocator> |
| 162 class DequeIterator : public DequeIteratorBase<T, inlineCapacity, Allocator> { | 179 class DequeIterator : public DequeIteratorBase<T, inlineCapacity, Allocator> { |
| 163 private: | 180 private: |
| 164 typedef DequeIteratorBase<T, inlineCapacity, Allocator> Base; | 181 typedef DequeIteratorBase<T, inlineCapacity, Allocator> Base; |
| 165 typedef DequeIterator<T, inlineCapacity, Allocator> Iterator; | 182 typedef DequeIterator<T, inlineCapacity, Allocator> Iterator; |
| 166 | 183 |
| 167 public: | 184 public: |
| 168 typedef ptrdiff_t difference_type; | 185 typedef ptrdiff_t difference_type; |
| 169 typedef T value_type; | 186 typedef T value_type; |
| 170 typedef T* pointer; | 187 typedef T* pointer; |
| 171 typedef T& reference; | 188 typedef T& reference; |
| 172 typedef std::bidirectional_iterator_tag iterator_category; | 189 typedef std::bidirectional_iterator_tag iterator_category; |
| 173 | 190 |
| 174 DequeIterator(Deque<T, inlineCapacity, Allocator>* deque, size_t index) : Ba
se(deque, index) {} | 191 DequeIterator(Deque<T, inlineCapacity, Allocator>* deque, size_t index) |
| 175 | 192 : Base(deque, index) {} |
| 176 DequeIterator(const Iterator& other) : Base(other) {} | 193 |
| 177 DequeIterator& operator=(const Iterator& other) { Base::assign(other); retur
n *this; } | 194 DequeIterator(const Iterator& other) |
| 178 | 195 : Base(other) {} |
| 179 T& operator*() const { return *Base::after(); } | 196 DequeIterator& operator=(const Iterator& other) { |
| 180 T* operator->() const { return Base::after(); } | 197 Base::assign(other); |
| 181 | 198 return *this; |
| 182 bool operator==(const Iterator& other) const { return Base::isEqual(other);
} | 199 } |
| 183 bool operator!=(const Iterator& other) const { return !Base::isEqual(other);
} | 200 |
| 184 | 201 T& operator*() const { return *Base::after(); } |
| 185 Iterator& operator++() { Base::increment(); return *this; } | 202 T* operator->() const { return Base::after(); } |
| 186 // postfix ++ intentionally omitted | 203 |
| 187 Iterator& operator--() { Base::decrement(); return *this; } | 204 bool operator==(const Iterator& other) const { return Base::isEqual(other); } |
| 188 // postfix -- intentionally omitted | 205 bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } |
| 206 |
| 207 Iterator& operator++() { |
| 208 Base::increment(); |
| 209 return *this; |
| 210 } |
| 211 // postfix ++ intentionally omitted |
| 212 Iterator& operator--() { |
| 213 Base::decrement(); |
| 214 return *this; |
| 215 } |
| 216 // postfix -- intentionally omitted |
| 189 }; | 217 }; |
| 190 | 218 |
| 191 template <typename T, size_t inlineCapacity = 0, typename Allocator = PartitionA
llocator> | 219 template <typename T, size_t inlineCapacity = 0, typename Allocator = PartitionA
llocator> |
| 192 class DequeConstIterator : public DequeIteratorBase<T, inlineCapacity, Allocator
> { | 220 class DequeConstIterator : public DequeIteratorBase<T, inlineCapacity, Allocator
> { |
| 193 private: | 221 private: |
| 194 typedef DequeIteratorBase<T, inlineCapacity, Allocator> Base; | 222 typedef DequeIteratorBase<T, inlineCapacity, Allocator> Base; |
| 195 typedef DequeConstIterator<T, inlineCapacity, Allocator> Iterator; | 223 typedef DequeConstIterator<T, inlineCapacity, Allocator> Iterator; |
| 196 typedef DequeIterator<T, inlineCapacity, Allocator> NonConstIterator; | 224 typedef DequeIterator<T, inlineCapacity, Allocator> NonConstIterator; |
| 197 | 225 |
| 198 public: | 226 public: |
| 199 typedef ptrdiff_t difference_type; | 227 typedef ptrdiff_t difference_type; |
| 200 typedef T value_type; | 228 typedef T value_type; |
| 201 typedef const T* pointer; | 229 typedef const T* pointer; |
| 202 typedef const T& reference; | 230 typedef const T& reference; |
| 203 typedef std::bidirectional_iterator_tag iterator_category; | 231 typedef std::bidirectional_iterator_tag iterator_category; |
| 204 | 232 |
| 205 DequeConstIterator(const Deque<T, inlineCapacity, Allocator>* deque, size_t
index) : Base(deque, index) {} | 233 DequeConstIterator(const Deque<T, inlineCapacity, Allocator>* deque, size_t in
dex) |
| 206 | 234 : Base(deque, index) {} |
| 207 DequeConstIterator(const Iterator& other) : Base(other) {} | 235 |
| 208 DequeConstIterator(const NonConstIterator& other) : Base(other) {} | 236 DequeConstIterator(const Iterator& other) |
| 209 DequeConstIterator& operator=(const Iterator& other) { Base::assign(other);
return *this; } | 237 : Base(other) {} |
| 210 DequeConstIterator& operator=(const NonConstIterator& other) { Base::assign(
other); return *this; } | 238 DequeConstIterator(const NonConstIterator& other) |
| 211 | 239 : Base(other) {} |
| 212 const T& operator*() const { return *Base::after(); } | 240 DequeConstIterator& operator=(const Iterator& other) { |
| 213 const T* operator->() const { return Base::after(); } | 241 Base::assign(other); |
| 214 | 242 return *this; |
| 215 bool operator==(const Iterator& other) const { return Base::isEqual(other);
} | 243 } |
| 216 bool operator!=(const Iterator& other) const { return !Base::isEqual(other);
} | 244 DequeConstIterator& operator=(const NonConstIterator& other) { |
| 217 | 245 Base::assign(other); |
| 218 Iterator& operator++() { Base::increment(); return *this; } | 246 return *this; |
| 219 // postfix ++ intentionally omitted | 247 } |
| 220 Iterator& operator--() { Base::decrement(); return *this; } | 248 |
| 221 // postfix -- intentionally omitted | 249 const T& operator*() const { return *Base::after(); } |
| 250 const T* operator->() const { return Base::after(); } |
| 251 |
| 252 bool operator==(const Iterator& other) const { return Base::isEqual(other); } |
| 253 bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } |
| 254 |
| 255 Iterator& operator++() { |
| 256 Base::increment(); |
| 257 return *this; |
| 258 } |
| 259 // postfix ++ intentionally omitted |
| 260 Iterator& operator--() { |
| 261 Base::decrement(); |
| 262 return *this; |
| 263 } |
| 264 // postfix -- intentionally omitted |
| 222 }; | 265 }; |
| 223 | 266 |
| 224 template <typename T, size_t inlineCapacity, typename Allocator> | 267 template <typename T, size_t inlineCapacity, typename Allocator> |
| 225 inline Deque<T, inlineCapacity, Allocator>::Deque() | 268 inline Deque<T, inlineCapacity, Allocator>::Deque() |
| 226 : m_start(0) | 269 : m_start(0), m_end(0) { |
| 227 , m_end(0) | 270 static_assert(!IsPolymorphic<T>::value || !VectorTraits<T>::canInitializeWithM
emset, "Cannot initialize with memset if there is a vtable"); |
| 228 { | |
| 229 static_assert(!IsPolymorphic<T>::value || !VectorTraits<T>::canInitializeWit
hMemset, "Cannot initialize with memset if there is a vtable"); | |
| 230 #if ENABLE(OILPAN) | 271 #if ENABLE(OILPAN) |
| 231 static_assert(Allocator::isGarbageCollected || !AllowsOnlyPlacementNew<T>::v
alue || !NeedsTracing<T>::value, "Cannot put DISALLOW_NEW_EXCEPT_PLACEMENT_NEW o
bjects that have trace methods into an off-heap Deque"); | 272 static_assert(Allocator::isGarbageCollected || !AllowsOnlyPlacementNew<T>::val
ue || !NeedsTracing<T>::value, "Cannot put DISALLOW_NEW_EXCEPT_PLACEMENT_NEW obj
ects that have trace methods into an off-heap Deque"); |
| 232 #endif | 273 #endif |
| 233 static_assert(Allocator::isGarbageCollected || !IsPointerToGarbageCollectedT
ype<T>::value, "Cannot put raw pointers to garbage-collected classes into a Dequ
e. Use HeapDeque<Member<T>> instead."); | 274 static_assert(Allocator::isGarbageCollected || !IsPointerToGarbageCollectedTyp
e<T>::value, "Cannot put raw pointers to garbage-collected classes into a Deque.
Use HeapDeque<Member<T>> instead."); |
| 234 } | 275 } |
| 235 | 276 |
| 236 template <typename T, size_t inlineCapacity, typename Allocator> | 277 template <typename T, size_t inlineCapacity, typename Allocator> |
| 237 inline Deque<T, inlineCapacity, Allocator>::Deque(const Deque<T, inlineCapacity,
Allocator>& other) | 278 inline Deque<T, inlineCapacity, Allocator>::Deque(const Deque<T, inlineCapacity,
Allocator>& other) |
| 238 : m_buffer(other.m_buffer.capacity()) | 279 : m_buffer(other.m_buffer.capacity()), m_start(other.m_start), m_end(other.m
_end) { |
| 239 , m_start(other.m_start) | 280 const T* otherBuffer = other.m_buffer.buffer(); |
| 240 , m_end(other.m_end) | 281 if (m_start <= m_end) { |
| 241 { | 282 TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_end
, m_buffer.buffer() + m_start); |
| 242 const T* otherBuffer = other.m_buffer.buffer(); | 283 } else { |
| 243 if (m_start <= m_end) { | 284 TypeOperations::uninitializedCopy(otherBuffer, otherBuffer + m_end, m_buffer
.buffer()); |
| 244 TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m
_end, m_buffer.buffer() + m_start); | 285 TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_buf
fer.capacity(), m_buffer.buffer() + m_start); |
| 245 } else { | 286 } |
| 246 TypeOperations::uninitializedCopy(otherBuffer, otherBuffer + m_end, m_bu
ffer.buffer()); | 287 } |
| 247 TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m
_buffer.capacity(), m_buffer.buffer() + m_start); | 288 |
| 248 } | 289 template <typename T, size_t inlineCapacity, typename Allocator> |
| 249 } | 290 inline Deque<T, 0, Allocator>& Deque<T, inlineCapacity, Allocator>::operator=(co
nst Deque& other) { |
| 250 | 291 Deque<T> copy(other); |
| 251 template <typename T, size_t inlineCapacity, typename Allocator> | 292 swap(copy); |
| 252 inline Deque<T, 0, Allocator>& Deque<T, inlineCapacity, Allocator>::operator=(co
nst Deque& other) | 293 return *this; |
| 253 { | 294 } |
| 254 Deque<T> copy(other); | 295 |
| 255 swap(copy); | 296 template <typename T, size_t inlineCapacity, typename Allocator> |
| 256 return *this; | 297 inline void Deque<T, inlineCapacity, Allocator>::destroyAll() { |
| 257 } | 298 if (m_start <= m_end) { |
| 258 | 299 TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_
end); |
| 259 template <typename T, size_t inlineCapacity, typename Allocator> | 300 m_buffer.clearUnusedSlots(m_buffer.buffer() + m_start, m_buffer.buffer() + m
_end); |
| 260 inline void Deque<T, inlineCapacity, Allocator>::destroyAll() | 301 } else { |
| 261 { | 302 TypeOperations::destruct(m_buffer.buffer(), m_buffer.buffer() + m_end); |
| 262 if (m_start <= m_end) { | 303 m_buffer.clearUnusedSlots(m_buffer.buffer(), m_buffer.buffer() + m_end); |
| 263 TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer()
+ m_end); | 304 TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_
buffer.capacity()); |
| 264 m_buffer.clearUnusedSlots(m_buffer.buffer() + m_start, m_buffer.buffer()
+ m_end); | 305 m_buffer.clearUnusedSlots(m_buffer.buffer() + m_start, m_buffer.buffer() + m
_buffer.capacity()); |
| 265 } else { | 306 } |
| 266 TypeOperations::destruct(m_buffer.buffer(), m_buffer.buffer() + m_end); | |
| 267 m_buffer.clearUnusedSlots(m_buffer.buffer(), m_buffer.buffer() + m_end); | |
| 268 TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer()
+ m_buffer.capacity()); | |
| 269 m_buffer.clearUnusedSlots(m_buffer.buffer() + m_start, m_buffer.buffer()
+ m_buffer.capacity()); | |
| 270 } | |
| 271 } | 307 } |
| 272 | 308 |
| 273 // Off-GC-heap deques: Destructor should be called. | 309 // Off-GC-heap deques: Destructor should be called. |
| 274 // On-GC-heap deques: Destructor should be called for inline buffers (if any) | 310 // On-GC-heap deques: Destructor should be called for inline buffers (if any) |
| 275 // but destructor shouldn't be called for vector backing since it is managed by | 311 // but destructor shouldn't be called for vector backing since it is managed by |
| 276 // the traced GC heap. | 312 // the traced GC heap. |
| 277 template <typename T, size_t inlineCapacity, typename Allocator> | 313 template <typename T, size_t inlineCapacity, typename Allocator> |
| 278 inline void Deque<T, inlineCapacity, Allocator>::finalize() | 314 inline void Deque<T, inlineCapacity, Allocator>::finalize() { |
| 279 { | 315 if (!INLINE_CAPACITY && !m_buffer.buffer()) |
| 280 if (!INLINE_CAPACITY && !m_buffer.buffer()) | 316 return; |
| 281 return; | 317 if (!isEmpty() && !(Allocator::isGarbageCollected && m_buffer.hasOutOfLineBuff
er())) |
| 282 if (!isEmpty() && !(Allocator::isGarbageCollected && m_buffer.hasOutOfLineBu
ffer())) | 318 destroyAll(); |
| 283 destroyAll(); | 319 |
| 284 | 320 m_buffer.destruct(); |
| 285 m_buffer.destruct(); | |
| 286 } | 321 } |
| 287 | 322 |
| 288 // FIXME: Doesn't work if there is an inline buffer, due to crbug.com/360572 | 323 // FIXME: Doesn't work if there is an inline buffer, due to crbug.com/360572 |
| 289 template <typename T, size_t inlineCapacity, typename Allocator> | 324 template <typename T, size_t inlineCapacity, typename Allocator> |
| 290 inline void Deque<T, inlineCapacity, Allocator>::swap(Deque<T, 0, Allocator>& ot
her) | 325 inline void Deque<T, inlineCapacity, Allocator>::swap(Deque<T, 0, Allocator>& ot
her) { |
| 291 { | 326 std::swap(m_start, other.m_start); |
| 292 std::swap(m_start, other.m_start); | 327 std::swap(m_end, other.m_end); |
| 293 std::swap(m_end, other.m_end); | 328 m_buffer.swapVectorBuffer(other.m_buffer); |
| 294 m_buffer.swapVectorBuffer(other.m_buffer); | 329 } |
| 295 } | 330 |
| 296 | 331 template <typename T, size_t inlineCapacity, typename Allocator> |
| 297 template <typename T, size_t inlineCapacity, typename Allocator> | 332 inline void Deque<T, inlineCapacity, Allocator>::clear() { |
| 298 inline void Deque<T, inlineCapacity, Allocator>::clear() | 333 destroyAll(); |
| 299 { | 334 m_start = 0; |
| 300 destroyAll(); | 335 m_end = 0; |
| 336 m_buffer.deallocateBuffer(m_buffer.buffer()); |
| 337 m_buffer.resetBufferPointer(); |
| 338 } |
| 339 |
| 340 template <typename T, size_t inlineCapacity, typename Allocator> |
| 341 template <typename Predicate> |
| 342 inline DequeIterator<T, inlineCapacity, Allocator> Deque<T, inlineCapacity, Allo
cator>::findIf(Predicate& predicate) { |
| 343 iterator endIterator = end(); |
| 344 for (iterator it = begin(); it != endIterator; ++it) { |
| 345 if (predicate(*it)) |
| 346 return it; |
| 347 } |
| 348 return endIterator; |
| 349 } |
| 350 |
| 351 template <typename T, size_t inlineCapacity, typename Allocator> |
| 352 inline void Deque<T, inlineCapacity, Allocator>::expandCapacityIfNeeded() { |
| 353 if (m_start) { |
| 354 if (m_end + 1 != m_start) |
| 355 return; |
| 356 } else if (m_end) { |
| 357 if (m_end != m_buffer.capacity() - 1) |
| 358 return; |
| 359 } else if (m_buffer.capacity()) { |
| 360 return; |
| 361 } |
| 362 |
| 363 expandCapacity(); |
| 364 } |
| 365 |
| 366 template <typename T, size_t inlineCapacity, typename Allocator> |
| 367 void Deque<T, inlineCapacity, Allocator>::expandCapacity() { |
| 368 size_t oldCapacity = m_buffer.capacity(); |
| 369 T* oldBuffer = m_buffer.buffer(); |
| 370 size_t newCapacity = std::max(static_cast<size_t>(16), oldCapacity + oldCapaci
ty / 4 + 1); |
| 371 if (m_buffer.expandBuffer(newCapacity)) { |
| 372 if (m_start <= m_end) { |
| 373 // No adjustments to be done. |
| 374 } else { |
| 375 size_t newStart = m_buffer.capacity() - (oldCapacity - m_start); |
| 376 TypeOperations::moveOverlapping(oldBuffer + m_start, oldBuffer + oldCapaci
ty, m_buffer.buffer() + newStart); |
| 377 m_buffer.clearUnusedSlots(oldBuffer + m_start, oldBuffer + std::min(oldCap
acity, newStart)); |
| 378 m_start = newStart; |
| 379 } |
| 380 return; |
| 381 } |
| 382 m_buffer.allocateBuffer(newCapacity); |
| 383 if (m_start <= m_end) { |
| 384 TypeOperations::move(oldBuffer + m_start, oldBuffer + m_end, m_buffer.buffer
() + m_start); |
| 385 m_buffer.clearUnusedSlots(oldBuffer + m_start, oldBuffer + m_end); |
| 386 } else { |
| 387 TypeOperations::move(oldBuffer, oldBuffer + m_end, m_buffer.buffer()); |
| 388 m_buffer.clearUnusedSlots(oldBuffer, oldBuffer + m_end); |
| 389 size_t newStart = m_buffer.capacity() - (oldCapacity - m_start); |
| 390 TypeOperations::move(oldBuffer + m_start, oldBuffer + oldCapacity, m_buffer.
buffer() + newStart); |
| 391 m_buffer.clearUnusedSlots(oldBuffer + m_start, oldBuffer + oldCapacity); |
| 392 m_start = newStart; |
| 393 } |
| 394 m_buffer.deallocateBuffer(oldBuffer); |
| 395 } |
| 396 |
| 397 template <typename T, size_t inlineCapacity, typename Allocator> |
| 398 inline typename Deque<T, inlineCapacity, Allocator>::PassType Deque<T, inlineCap
acity, Allocator>::takeFirst() { |
| 399 T oldFirst = Pass::transfer(first()); |
| 400 removeFirst(); |
| 401 return Pass::transfer(oldFirst); |
| 402 } |
| 403 |
| 404 template <typename T, size_t inlineCapacity, typename Allocator> |
| 405 inline typename Deque<T, inlineCapacity, Allocator>::PassType Deque<T, inlineCap
acity, Allocator>::takeLast() { |
| 406 T oldLast = Pass::transfer(last()); |
| 407 removeLast(); |
| 408 return Pass::transfer(oldLast); |
| 409 } |
| 410 |
| 411 template <typename T, size_t inlineCapacity, typename Allocator> |
| 412 template <typename U> |
| 413 inline void Deque<T, inlineCapacity, Allocator>::append(const U& value) { |
| 414 expandCapacityIfNeeded(); |
| 415 new (NotNull, &m_buffer.buffer()[m_end]) T(value); |
| 416 if (m_end == m_buffer.capacity() - 1) |
| 417 m_end = 0; |
| 418 else |
| 419 ++m_end; |
| 420 } |
| 421 |
| 422 template <typename T, size_t inlineCapacity, typename Allocator> |
| 423 template <typename U> |
| 424 inline void Deque<T, inlineCapacity, Allocator>::prepend(const U& value) { |
| 425 expandCapacityIfNeeded(); |
| 426 if (!m_start) |
| 427 m_start = m_buffer.capacity() - 1; |
| 428 else |
| 429 --m_start; |
| 430 new (NotNull, &m_buffer.buffer()[m_start]) T(value); |
| 431 } |
| 432 |
| 433 template <typename T, size_t inlineCapacity, typename Allocator> |
| 434 inline void Deque<T, inlineCapacity, Allocator>::removeFirst() { |
| 435 ASSERT(!isEmpty()); |
| 436 TypeOperations::destruct(&m_buffer.buffer()[m_start], &m_buffer.buffer()[m_sta
rt + 1]); |
| 437 m_buffer.clearUnusedSlots(&m_buffer.buffer()[m_start], &m_buffer.buffer()[m_st
art + 1]); |
| 438 if (m_start == m_buffer.capacity() - 1) |
| 301 m_start = 0; | 439 m_start = 0; |
| 302 m_end = 0; | 440 else |
| 303 m_buffer.deallocateBuffer(m_buffer.buffer()); | 441 ++m_start; |
| 304 m_buffer.resetBufferPointer(); | 442 } |
| 305 } | 443 |
| 306 | 444 template <typename T, size_t inlineCapacity, typename Allocator> |
| 307 template <typename T, size_t inlineCapacity, typename Allocator> | 445 inline void Deque<T, inlineCapacity, Allocator>::removeLast() { |
| 308 template <typename Predicate> | 446 ASSERT(!isEmpty()); |
| 309 inline DequeIterator<T, inlineCapacity, Allocator> Deque<T, inlineCapacity, Allo
cator>::findIf(Predicate& predicate) | 447 if (!m_end) |
| 310 { | 448 m_end = m_buffer.capacity() - 1; |
| 311 iterator endIterator = end(); | 449 else |
| 312 for (iterator it = begin(); it != endIterator; ++it) { | 450 --m_end; |
| 313 if (predicate(*it)) | 451 TypeOperations::destruct(&m_buffer.buffer()[m_end], &m_buffer.buffer()[m_end +
1]); |
| 314 return it; | 452 m_buffer.clearUnusedSlots(&m_buffer.buffer()[m_end], &m_buffer.buffer()[m_end
+ 1]); |
| 315 } | 453 } |
| 316 return endIterator; | 454 |
| 317 } | 455 template <typename T, size_t inlineCapacity, typename Allocator> |
| 318 | 456 inline void Deque<T, inlineCapacity, Allocator>::remove(iterator& it) { |
| 319 template <typename T, size_t inlineCapacity, typename Allocator> | 457 remove(it.m_index); |
| 320 inline void Deque<T, inlineCapacity, Allocator>::expandCapacityIfNeeded() | 458 } |
| 321 { | 459 |
| 322 if (m_start) { | 460 template <typename T, size_t inlineCapacity, typename Allocator> |
| 323 if (m_end + 1 != m_start) | 461 inline void Deque<T, inlineCapacity, Allocator>::remove(const_iterator& it) { |
| 324 return; | 462 remove(it.m_index); |
| 325 } else if (m_end) { | 463 } |
| 326 if (m_end != m_buffer.capacity() - 1) | 464 |
| 327 return; | 465 template <typename T, size_t inlineCapacity, typename Allocator> |
| 328 } else if (m_buffer.capacity()) { | 466 inline void Deque<T, inlineCapacity, Allocator>::remove(size_t position) { |
| 329 return; | 467 if (position == m_end) |
| 330 } | 468 return; |
| 331 | 469 |
| 332 expandCapacity(); | 470 T* buffer = m_buffer.buffer(); |
| 333 } | 471 TypeOperations::destruct(&buffer[position], &buffer[position + 1]); |
| 334 | 472 |
| 335 template <typename T, size_t inlineCapacity, typename Allocator> | 473 // Find which segment of the circular buffer contained the remove element, |
| 336 void Deque<T, inlineCapacity, Allocator>::expandCapacity() | 474 // and only move elements in that part. |
| 337 { | 475 if (position >= m_start) { |
| 338 size_t oldCapacity = m_buffer.capacity(); | 476 TypeOperations::moveOverlapping(buffer + m_start, buffer + position, buffer
+ m_start + 1); |
| 339 T* oldBuffer = m_buffer.buffer(); | 477 m_buffer.clearUnusedSlots(buffer + m_start, buffer + m_start + 1); |
| 340 size_t newCapacity = std::max(static_cast<size_t>(16), oldCapacity + oldCapa
city / 4 + 1); | 478 m_start = (m_start + 1) % m_buffer.capacity(); |
| 341 if (m_buffer.expandBuffer(newCapacity)) { | 479 } else { |
| 342 if (m_start <= m_end) { | 480 TypeOperations::moveOverlapping(buffer + position + 1, buffer + m_end, buffe
r + position); |
| 343 // No adjustments to be done. | 481 m_buffer.clearUnusedSlots(buffer + m_end - 1, buffer + m_end); |
| 344 } else { | 482 m_end = (m_end - 1 + m_buffer.capacity()) % m_buffer.capacity(); |
| 345 size_t newStart = m_buffer.capacity() - (oldCapacity - m_start); | 483 } |
| 346 TypeOperations::moveOverlapping(oldBuffer + m_start, oldBuffer + old
Capacity, m_buffer.buffer() + newStart); | |
| 347 m_buffer.clearUnusedSlots(oldBuffer + m_start, oldBuffer + std::min(
oldCapacity, newStart)); | |
| 348 m_start = newStart; | |
| 349 } | |
| 350 return; | |
| 351 } | |
| 352 m_buffer.allocateBuffer(newCapacity); | |
| 353 if (m_start <= m_end) { | |
| 354 TypeOperations::move(oldBuffer + m_start, oldBuffer + m_end, m_buffer.bu
ffer() + m_start); | |
| 355 m_buffer.clearUnusedSlots(oldBuffer + m_start, oldBuffer + m_end); | |
| 356 } else { | |
| 357 TypeOperations::move(oldBuffer, oldBuffer + m_end, m_buffer.buffer()); | |
| 358 m_buffer.clearUnusedSlots(oldBuffer, oldBuffer + m_end); | |
| 359 size_t newStart = m_buffer.capacity() - (oldCapacity - m_start); | |
| 360 TypeOperations::move(oldBuffer + m_start, oldBuffer + oldCapacity, m_buf
fer.buffer() + newStart); | |
| 361 m_buffer.clearUnusedSlots(oldBuffer + m_start, oldBuffer + oldCapacity); | |
| 362 m_start = newStart; | |
| 363 } | |
| 364 m_buffer.deallocateBuffer(oldBuffer); | |
| 365 } | |
| 366 | |
| 367 template <typename T, size_t inlineCapacity, typename Allocator> | |
| 368 inline typename Deque<T, inlineCapacity, Allocator>::PassType Deque<T, inlineCap
acity, Allocator>::takeFirst() | |
| 369 { | |
| 370 T oldFirst = Pass::transfer(first()); | |
| 371 removeFirst(); | |
| 372 return Pass::transfer(oldFirst); | |
| 373 } | |
| 374 | |
| 375 template <typename T, size_t inlineCapacity, typename Allocator> | |
| 376 inline typename Deque<T, inlineCapacity, Allocator>::PassType Deque<T, inlineCap
acity, Allocator>::takeLast() | |
| 377 { | |
| 378 T oldLast = Pass::transfer(last()); | |
| 379 removeLast(); | |
| 380 return Pass::transfer(oldLast); | |
| 381 } | |
| 382 | |
| 383 template <typename T, size_t inlineCapacity, typename Allocator> | |
| 384 template <typename U> | |
| 385 inline void Deque<T, inlineCapacity, Allocator>::append(const U& value) | |
| 386 { | |
| 387 expandCapacityIfNeeded(); | |
| 388 new (NotNull, &m_buffer.buffer()[m_end]) T(value); | |
| 389 if (m_end == m_buffer.capacity() - 1) | |
| 390 m_end = 0; | |
| 391 else | |
| 392 ++m_end; | |
| 393 } | |
| 394 | |
| 395 template <typename T, size_t inlineCapacity, typename Allocator> | |
| 396 template <typename U> | |
| 397 inline void Deque<T, inlineCapacity, Allocator>::prepend(const U& value) | |
| 398 { | |
| 399 expandCapacityIfNeeded(); | |
| 400 if (!m_start) | |
| 401 m_start = m_buffer.capacity() - 1; | |
| 402 else | |
| 403 --m_start; | |
| 404 new (NotNull, &m_buffer.buffer()[m_start]) T(value); | |
| 405 } | |
| 406 | |
| 407 template <typename T, size_t inlineCapacity, typename Allocator> | |
| 408 inline void Deque<T, inlineCapacity, Allocator>::removeFirst() | |
| 409 { | |
| 410 ASSERT(!isEmpty()); | |
| 411 TypeOperations::destruct(&m_buffer.buffer()[m_start], &m_buffer.buffer()[m_s
tart + 1]); | |
| 412 m_buffer.clearUnusedSlots(&m_buffer.buffer()[m_start], &m_buffer.buffer()[m_
start + 1]); | |
| 413 if (m_start == m_buffer.capacity() - 1) | |
| 414 m_start = 0; | |
| 415 else | |
| 416 ++m_start; | |
| 417 } | |
| 418 | |
| 419 template <typename T, size_t inlineCapacity, typename Allocator> | |
| 420 inline void Deque<T, inlineCapacity, Allocator>::removeLast() | |
| 421 { | |
| 422 ASSERT(!isEmpty()); | |
| 423 if (!m_end) | |
| 424 m_end = m_buffer.capacity() - 1; | |
| 425 else | |
| 426 --m_end; | |
| 427 TypeOperations::destruct(&m_buffer.buffer()[m_end], &m_buffer.buffer()[m_end
+ 1]); | |
| 428 m_buffer.clearUnusedSlots(&m_buffer.buffer()[m_end], &m_buffer.buffer()[m_en
d + 1]); | |
| 429 } | |
| 430 | |
| 431 template <typename T, size_t inlineCapacity, typename Allocator> | |
| 432 inline void Deque<T, inlineCapacity, Allocator>::remove(iterator& it) | |
| 433 { | |
| 434 remove(it.m_index); | |
| 435 } | |
| 436 | |
| 437 template <typename T, size_t inlineCapacity, typename Allocator> | |
| 438 inline void Deque<T, inlineCapacity, Allocator>::remove(const_iterator& it) | |
| 439 { | |
| 440 remove(it.m_index); | |
| 441 } | |
| 442 | |
| 443 template <typename T, size_t inlineCapacity, typename Allocator> | |
| 444 inline void Deque<T, inlineCapacity, Allocator>::remove(size_t position) | |
| 445 { | |
| 446 if (position == m_end) | |
| 447 return; | |
| 448 | |
| 449 T* buffer = m_buffer.buffer(); | |
| 450 TypeOperations::destruct(&buffer[position], &buffer[position + 1]); | |
| 451 | |
| 452 // Find which segment of the circular buffer contained the remove element, | |
| 453 // and only move elements in that part. | |
| 454 if (position >= m_start) { | |
| 455 TypeOperations::moveOverlapping(buffer + m_start, buffer + position, buf
fer + m_start + 1); | |
| 456 m_buffer.clearUnusedSlots(buffer + m_start, buffer + m_start + 1); | |
| 457 m_start = (m_start + 1) % m_buffer.capacity(); | |
| 458 } else { | |
| 459 TypeOperations::moveOverlapping(buffer + position + 1, buffer + m_end, b
uffer + position); | |
| 460 m_buffer.clearUnusedSlots(buffer + m_end - 1, buffer + m_end); | |
| 461 m_end = (m_end - 1 + m_buffer.capacity()) % m_buffer.capacity(); | |
| 462 } | |
| 463 } | 484 } |
| 464 | 485 |
| 465 template <typename T, size_t inlineCapacity, typename Allocator> | 486 template <typename T, size_t inlineCapacity, typename Allocator> |
| 466 inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase() | 487 inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase() |
| 467 : m_deque(0) | 488 : m_deque(0) { |
| 468 { | |
| 469 } | 489 } |
| 470 | 490 |
| 471 template <typename T, size_t inlineCapacity, typename Allocator> | 491 template <typename T, size_t inlineCapacity, typename Allocator> |
| 472 inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase(const
Deque<T, inlineCapacity, Allocator>* deque, size_t index) | 492 inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase(const
Deque<T, inlineCapacity, Allocator>* deque, size_t index) |
| 473 : m_deque(const_cast<Deque<T, inlineCapacity, Allocator>*>(deque)) | 493 : m_deque(const_cast<Deque<T, inlineCapacity, Allocator>*>(deque)), m_index(
index) { |
| 474 , m_index(index) | |
| 475 { | |
| 476 } | 494 } |
| 477 | 495 |
| 478 template <typename T, size_t inlineCapacity, typename Allocator> | 496 template <typename T, size_t inlineCapacity, typename Allocator> |
| 479 inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase(const
DequeIteratorBase& other) | 497 inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase(const
DequeIteratorBase& other) |
| 480 : m_deque(other.m_deque) | 498 : m_deque(other.m_deque), m_index(other.m_index) { |
| 481 , m_index(other.m_index) | 499 } |
| 482 { | 500 |
| 483 } | 501 template <typename T, size_t inlineCapacity, typename Allocator> |
| 484 | 502 inline DequeIteratorBase<T, 0, Allocator>& DequeIteratorBase<T, inlineCapacity,
Allocator>::operator=(const DequeIteratorBase<T, 0, Allocator>& other) { |
| 485 template <typename T, size_t inlineCapacity, typename Allocator> | 503 m_deque = other.m_deque; |
| 486 inline DequeIteratorBase<T, 0, Allocator>& DequeIteratorBase<T, inlineCapacity,
Allocator>::operator=(const DequeIteratorBase<T, 0, Allocator>& other) | 504 m_index = other.m_index; |
| 487 { | 505 return *this; |
| 488 m_deque = other.m_deque; | 506 } |
| 489 m_index = other.m_index; | 507 |
| 490 return *this; | 508 template <typename T, size_t inlineCapacity, typename Allocator> |
| 491 } | 509 inline DequeIteratorBase<T, inlineCapacity, Allocator>::~DequeIteratorBase() { |
| 492 | 510 } |
| 493 template <typename T, size_t inlineCapacity, typename Allocator> | 511 |
| 494 inline DequeIteratorBase<T, inlineCapacity, Allocator>::~DequeIteratorBase() | 512 template <typename T, size_t inlineCapacity, typename Allocator> |
| 495 { | 513 inline bool DequeIteratorBase<T, inlineCapacity, Allocator>::isEqual(const Deque
IteratorBase& other) const { |
| 496 } | 514 return m_index == other.m_index; |
| 497 | 515 } |
| 498 template <typename T, size_t inlineCapacity, typename Allocator> | 516 |
| 499 inline bool DequeIteratorBase<T, inlineCapacity, Allocator>::isEqual(const Deque
IteratorBase& other) const | 517 template <typename T, size_t inlineCapacity, typename Allocator> |
| 500 { | 518 inline void DequeIteratorBase<T, inlineCapacity, Allocator>::increment() { |
| 501 return m_index == other.m_index; | 519 ASSERT(m_index != m_deque->m_end); |
| 502 } | 520 ASSERT(m_deque->m_buffer.capacity()); |
| 503 | 521 if (m_index == m_deque->m_buffer.capacity() - 1) |
| 504 template <typename T, size_t inlineCapacity, typename Allocator> | 522 m_index = 0; |
| 505 inline void DequeIteratorBase<T, inlineCapacity, Allocator>::increment() | 523 else |
| 506 { | 524 ++m_index; |
| 507 ASSERT(m_index != m_deque->m_end); | 525 } |
| 508 ASSERT(m_deque->m_buffer.capacity()); | 526 |
| 509 if (m_index == m_deque->m_buffer.capacity() - 1) | 527 template <typename T, size_t inlineCapacity, typename Allocator> |
| 510 m_index = 0; | 528 inline void DequeIteratorBase<T, inlineCapacity, Allocator>::decrement() { |
| 511 else | 529 ASSERT(m_index != m_deque->m_start); |
| 512 ++m_index; | 530 ASSERT(m_deque->m_buffer.capacity()); |
| 513 } | 531 if (!m_index) |
| 514 | 532 m_index = m_deque->m_buffer.capacity() - 1; |
| 515 template <typename T, size_t inlineCapacity, typename Allocator> | 533 else |
| 516 inline void DequeIteratorBase<T, inlineCapacity, Allocator>::decrement() | 534 --m_index; |
| 517 { | 535 } |
| 518 ASSERT(m_index != m_deque->m_start); | 536 |
| 519 ASSERT(m_deque->m_buffer.capacity()); | 537 template <typename T, size_t inlineCapacity, typename Allocator> |
| 520 if (!m_index) | 538 inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::after() const { |
| 521 m_index = m_deque->m_buffer.capacity() - 1; | 539 ASSERT(m_index != m_deque->m_end); |
| 522 else | 540 return &m_deque->m_buffer.buffer()[m_index]; |
| 523 --m_index; | 541 } |
| 524 } | 542 |
| 525 | 543 template <typename T, size_t inlineCapacity, typename Allocator> |
| 526 template <typename T, size_t inlineCapacity, typename Allocator> | 544 inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::before() const { |
| 527 inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::after() const | 545 ASSERT(m_index != m_deque->m_start); |
| 528 { | 546 if (!m_index) |
| 529 ASSERT(m_index != m_deque->m_end); | 547 return &m_deque->m_buffer.buffer()[m_deque->m_buffer.capacity() - 1]; |
| 530 return &m_deque->m_buffer.buffer()[m_index]; | 548 return &m_deque->m_buffer.buffer()[m_index - 1]; |
| 531 } | |
| 532 | |
| 533 template <typename T, size_t inlineCapacity, typename Allocator> | |
| 534 inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::before() const | |
| 535 { | |
| 536 ASSERT(m_index != m_deque->m_start); | |
| 537 if (!m_index) | |
| 538 return &m_deque->m_buffer.buffer()[m_deque->m_buffer.capacity() - 1]; | |
| 539 return &m_deque->m_buffer.buffer()[m_index - 1]; | |
| 540 } | 549 } |
| 541 | 550 |
| 542 // This is only called if the allocator is a HeapAllocator. It is used when | 551 // This is only called if the allocator is a HeapAllocator. It is used when |
| 543 // visiting during a tracing GC. | 552 // visiting during a tracing GC. |
| 544 template <typename T, size_t inlineCapacity, typename Allocator> | 553 template <typename T, size_t inlineCapacity, typename Allocator> |
| 545 template <typename VisitorDispatcher> | 554 template <typename VisitorDispatcher> |
| 546 void Deque<T, inlineCapacity, Allocator>::trace(VisitorDispatcher visitor) | 555 void Deque<T, inlineCapacity, Allocator>::trace(VisitorDispatcher visitor) { |
| 547 { | 556 ASSERT(Allocator::isGarbageCollected); // Garbage collector must be enabled. |
| 548 ASSERT(Allocator::isGarbageCollected); // Garbage collector must be enabled. | 557 const T* bufferBegin = m_buffer.buffer(); |
| 549 const T* bufferBegin = m_buffer.buffer(); | 558 const T* end = bufferBegin + m_end; |
| 550 const T* end = bufferBegin + m_end; | 559 if (NeedsTracingTrait<VectorTraits<T>>::value) { |
| 551 if (NeedsTracingTrait<VectorTraits<T>>::value) { | 560 if (m_start <= m_end) { |
| 552 if (m_start <= m_end) { | 561 for (const T* bufferEntry = bufferBegin + m_start; bufferEntry != end; buf
ferEntry++) |
| 553 for (const T* bufferEntry = bufferBegin + m_start; bufferEntry != en
d; bufferEntry++) | 562 Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(visitor
, *const_cast<T*>(bufferEntry)); |
| 554 Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>
(visitor, *const_cast<T*>(bufferEntry)); | 563 } else { |
| 555 } else { | 564 for (const T* bufferEntry = bufferBegin; bufferEntry != end; bufferEntry++
) |
| 556 for (const T* bufferEntry = bufferBegin; bufferEntry != end; bufferE
ntry++) | 565 Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(visitor
, *const_cast<T*>(bufferEntry)); |
| 557 Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>
(visitor, *const_cast<T*>(bufferEntry)); | 566 const T* bufferEnd = m_buffer.buffer() + m_buffer.capacity(); |
| 558 const T* bufferEnd = m_buffer.buffer() + m_buffer.capacity(); | 567 for (const T* bufferEntry = bufferBegin + m_start; bufferEntry != bufferEn
d; bufferEntry++) |
| 559 for (const T* bufferEntry = bufferBegin + m_start; bufferEntry != bu
fferEnd; bufferEntry++) | 568 Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(visitor
, *const_cast<T*>(bufferEntry)); |
| 560 Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>
(visitor, *const_cast<T*>(bufferEntry)); | |
| 561 } | |
| 562 } | 569 } |
| 563 if (m_buffer.hasOutOfLineBuffer()) | 570 } |
| 564 Allocator::markNoTracing(visitor, m_buffer.buffer()); | 571 if (m_buffer.hasOutOfLineBuffer()) |
| 565 } | 572 Allocator::markNoTracing(visitor, m_buffer.buffer()); |
| 566 | 573 } |
| 567 template <typename T, size_t inlineCapacity, typename Allocator> | 574 |
| 568 inline void swap(Deque<T, inlineCapacity, Allocator>& a, Deque<T, inlineCapacity
, Allocator>& b) | 575 template <typename T, size_t inlineCapacity, typename Allocator> |
| 569 { | 576 inline void swap(Deque<T, inlineCapacity, Allocator>& a, Deque<T, inlineCapacity
, Allocator>& b) { |
| 570 a.swap(b); | 577 a.swap(b); |
| 571 } | 578 } |
| 572 | 579 |
| 573 #if !ENABLE(OILPAN) | 580 #if !ENABLE(OILPAN) |
| 574 template <typename T, size_t N> | 581 template <typename T, size_t N> |
| 575 struct NeedsTracing<Deque<T, N>> { | 582 struct NeedsTracing<Deque<T, N>> { |
| 576 static const bool value = false; | 583 static const bool value = false; |
| 577 }; | 584 }; |
| 578 #endif | 585 #endif |
| 579 | 586 |
| 580 } // namespace WTF | 587 } // namespace WTF |
| 581 | 588 |
| 582 using WTF::Deque; | 589 using WTF::Deque; |
| 583 | 590 |
| 584 #endif // WTF_Deque_h | 591 #endif // WTF_Deque_h |
| OLD | NEW |