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