Chromium Code Reviews| 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 25 matching lines...) Expand all Loading... | |
| 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 template<typename T, size_t inlineCapacity, typename Allocator> class DequeI teratorBase; | 41 template<typename T, size_t inlineCapacity, typename Allocator> class DequeI teratorBase; |
| 42 template<typename T, size_t inlineCapacity, typename Allocator> class DequeI terator; | 42 template<typename T, size_t inlineCapacity, typename Allocator> class DequeI terator; |
| 43 template<typename T, size_t inlineCapacity, typename Allocator> class DequeC onstIterator; | 43 template<typename T, size_t inlineCapacity, typename Allocator> class DequeC onstIterator; |
| 44 | 44 |
| 45 template<typename T, size_t inlineCapacity = 0, typename Allocator = Default Allocator> | 45 template<typename T, size_t inlineCapacity = 0, typename Allocator = Default Allocator> |
| 46 class Deque : public VectorDestructorBase<Deque<T, inlineCapacity, Allocator >, T, (inlineCapacity > 0), Allocator::isGarbageCollected> { | 46 class Deque : private VectorBuffer<T, inlineCapacity, Allocator>, public Vec torDestructorBase<Deque<T, inlineCapacity, Allocator>, T, (inlineCapacity > 0), Allocator::isGarbageCollected> { |
| 47 WTF_USE_ALLOCATOR(Deque, Allocator); | 47 WTF_USE_ALLOCATOR(Deque, Allocator); |
| 48 private: | |
| 49 private: | |
| 50 typedef VectorBuffer<T, inlineCapacity, Allocator> Base; | |
| 51 typedef typename Base::Range Range; | |
| 52 | |
| 48 public: | 53 public: |
| 49 typedef DequeIterator<T, inlineCapacity, Allocator> iterator; | 54 typedef DequeIterator<T, inlineCapacity, Allocator> iterator; |
| 50 typedef DequeConstIterator<T, inlineCapacity, Allocator> const_iterator; | 55 typedef DequeConstIterator<T, inlineCapacity, Allocator> const_iterator; |
| 51 typedef std::reverse_iterator<iterator> reverse_iterator; | 56 typedef std::reverse_iterator<iterator> reverse_iterator; |
| 52 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; | 57 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
| 53 typedef PassTraits<T> Pass; | 58 typedef PassTraits<T> Pass; |
| 54 typedef typename PassTraits<T>::PassType PassType; | 59 typedef typename PassTraits<T>::PassType PassType; |
| 55 | 60 |
| 56 Deque(); | 61 Deque(); |
| 57 Deque(const Deque<T, inlineCapacity, Allocator>&); | 62 Deque(const Deque<T, inlineCapacity, Allocator>&); |
| 58 // FIXME: Doesn't work if there is an inline buffer, due to crbug.com/36 0572 | 63 Deque<T, inlineCapacity, Allocator>& operator=(const Deque&); |
| 59 Deque<T, 0, Allocator>& operator=(const Deque&); | |
| 60 | 64 |
| 61 void finalize(); | 65 void finalize(); |
| 62 void finalizeGarbageCollectedObject() { finalize(); } | 66 void finalizeGarbageCollectedObject() { finalize(); } |
| 63 | 67 |
| 64 // We hard wire the inlineCapacity to zero here, due to crbug.com/360572 | 68 void swap(Deque<T, inlineCapacity, Allocator>&); |
| 65 void swap(Deque<T, 0, Allocator>&); | |
| 66 | 69 |
| 67 size_t size() const { return m_start <= m_end ? m_end - m_start : m_end + m_buffer.capacity() - m_start; } | 70 size_t size() const { return m_start <= m_end ? m_end - m_start : m_end + capacity() - m_start; } |
| 68 bool isEmpty() const { return m_start == m_end; } | 71 bool isEmpty() const { return m_start == m_end; } |
| 69 | 72 |
| 70 iterator begin() { return iterator(this, m_start); } | 73 iterator begin() { return iterator(this, m_start); } |
| 71 iterator end() { return iterator(this, m_end); } | 74 iterator end() { return iterator(this, m_end); } |
| 72 const_iterator begin() const { return const_iterator(this, m_start); } | 75 const_iterator begin() const { return const_iterator(this, m_start); } |
| 73 const_iterator end() const { return const_iterator(this, m_end); } | 76 const_iterator end() const { return const_iterator(this, m_end); } |
| 74 reverse_iterator rbegin() { return reverse_iterator(end()); } | 77 reverse_iterator rbegin() { return reverse_iterator(end()); } |
| 75 reverse_iterator rend() { return reverse_iterator(begin()); } | 78 reverse_iterator rend() { return reverse_iterator(begin()); } |
| 76 const_reverse_iterator rbegin() const { return const_reverse_iterator(en d()); } | 79 const_reverse_iterator rbegin() const { return const_reverse_iterator(en d()); } |
| 77 const_reverse_iterator rend() const { return const_reverse_iterator(begi n()); } | 80 const_reverse_iterator rend() const { return const_reverse_iterator(begi n()); } |
| 78 | 81 |
| 79 T& first() { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start] ; } | 82 T& first() { ASSERT(m_start != m_end); return buffer()[m_start]; } |
| 80 const T& first() const { ASSERT(m_start != m_end); return m_buffer.buffe r()[m_start]; } | 83 const T& first() const { ASSERT(m_start != m_end); return buffer()[m_sta rt]; } |
| 81 PassType takeFirst(); | 84 PassType takeFirst(); |
| 82 | 85 |
| 83 T& last() { ASSERT(m_start != m_end); return *(--end()); } | 86 T& last() { ASSERT(m_start != m_end); return *(--end()); } |
| 84 const T& last() const { ASSERT(m_start != m_end); return *(--end()); } | 87 const T& last() const { ASSERT(m_start != m_end); return *(--end()); } |
| 85 PassType takeLast(); | 88 PassType takeLast(); |
| 86 | 89 |
| 87 template<typename U> void append(const U&); | 90 template<typename U> void append(const U&); |
| 88 template<typename U> void prepend(const U&); | 91 template<typename U> void prepend(const U&); |
| 89 void removeFirst(); | 92 void removeFirst(); |
| 90 void removeLast(); | 93 void removeLast(); |
| 91 void remove(iterator&); | 94 void remove(iterator&); |
| 92 void remove(const_iterator&); | 95 void remove(const_iterator&); |
| 93 | 96 |
| 94 void clear(); | 97 void clear(); |
| 95 | 98 |
| 96 template<typename Predicate> | 99 template<typename Predicate> |
| 97 iterator findIf(Predicate&); | 100 iterator findIf(Predicate&); |
| 98 | 101 |
| 99 void trace(typename Allocator::Visitor*); | 102 void trace(typename Allocator::Visitor*); |
| 100 | 103 |
| 101 private: | 104 private: |
| 105 using Base::buffer; | |
| 106 using Base::capacity; | |
| 107 using Base::allocateBuffer; | |
| 108 using Base::clearUnusedSlots; | |
| 109 using Base::hasOutOfLineBuffer; | |
| 110 | |
| 102 friend class DequeIteratorBase<T, inlineCapacity, Allocator>; | 111 friend class DequeIteratorBase<T, inlineCapacity, Allocator>; |
| 112 friend class VectorBuffer<T, inlineCapacity, Allocator>; | |
| 103 | 113 |
| 104 typedef VectorBuffer<T, inlineCapacity, Allocator> Buffer; | |
| 105 typedef VectorTypeOperations<T> TypeOperations; | 114 typedef VectorTypeOperations<T> TypeOperations; |
| 106 typedef DequeIteratorBase<T, inlineCapacity, Allocator> IteratorBase; | 115 typedef DequeIteratorBase<T, inlineCapacity, Allocator> IteratorBase; |
| 107 | 116 |
| 108 void remove(size_t position); | 117 void remove(size_t position); |
| 109 void destroyAll(); | 118 void destroyAll(); |
| 110 void expandCapacityIfNeeded(); | 119 void expandCapacityIfNeeded(); |
| 111 void expandCapacity(); | 120 void expandCapacity(); |
| 112 | 121 |
| 113 Buffer m_buffer; | |
| 114 unsigned m_start; | 122 unsigned m_start; |
| 115 unsigned m_end; | 123 unsigned m_end; |
| 116 }; | 124 }; |
| 117 | 125 |
| 118 template<typename T, size_t inlineCapacity, typename Allocator> | 126 template<typename T, size_t inlineCapacity, typename Allocator> |
| 119 class DequeIteratorBase { | 127 class DequeIteratorBase { |
| 120 protected: | 128 protected: |
| 121 DequeIteratorBase(); | 129 DequeIteratorBase(); |
| 122 DequeIteratorBase(const Deque<T, inlineCapacity, Allocator>*, size_t); | 130 DequeIteratorBase(const Deque<T, inlineCapacity, Allocator>*, size_t); |
| 123 DequeIteratorBase(const DequeIteratorBase&); | 131 DequeIteratorBase(const DequeIteratorBase&); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 206 | 214 |
| 207 template<typename T, size_t inlineCapacity, typename Allocator> | 215 template<typename T, size_t inlineCapacity, typename Allocator> |
| 208 inline Deque<T, inlineCapacity, Allocator>::Deque() | 216 inline Deque<T, inlineCapacity, Allocator>::Deque() |
| 209 : m_start(0) | 217 : m_start(0) |
| 210 , m_end(0) | 218 , m_end(0) |
| 211 { | 219 { |
| 212 } | 220 } |
| 213 | 221 |
| 214 template<typename T, size_t inlineCapacity, typename Allocator> | 222 template<typename T, size_t inlineCapacity, typename Allocator> |
| 215 inline Deque<T, inlineCapacity, Allocator>::Deque(const Deque<T, inlineCapac ity, Allocator>& other) | 223 inline Deque<T, inlineCapacity, Allocator>::Deque(const Deque<T, inlineCapac ity, Allocator>& other) |
| 216 : m_buffer(other.m_buffer.capacity()) | 224 : VectorBuffer<T, inlineCapacity, Allocator>(other.capacity()) |
| 217 , m_start(other.m_start) | 225 , m_start(other.m_start) |
| 218 , m_end(other.m_end) | 226 , m_end(other.m_end) |
| 219 { | 227 { |
| 220 const T* otherBuffer = other.m_buffer.buffer(); | 228 const T* otherBuffer = other.buffer(); |
| 221 if (m_start <= m_end) | 229 if (m_start <= m_end) |
| 222 TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_end, m_buffer.buffer() + m_start); | 230 TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_end, buffer() + m_start); |
| 223 else { | 231 else { |
| 224 TypeOperations::uninitializedCopy(otherBuffer, otherBuffer + m_end, m_buffer.buffer()); | 232 TypeOperations::uninitializedCopy(otherBuffer, otherBuffer + m_end, buffer()); |
| 225 TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_buffer.capacity(), m_buffer.buffer() + m_start); | 233 TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + capacity(), buffer() + m_start); |
| 226 } | 234 } |
| 227 } | 235 } |
| 228 | 236 |
| 229 template<typename T, size_t inlineCapacity, typename Allocator> | 237 template<typename T, size_t inlineCapacity, typename Allocator> |
| 230 void deleteAllValues(const Deque<T, inlineCapacity, Allocator>& collection) | 238 void deleteAllValues(const Deque<T, inlineCapacity, Allocator>& collection) |
| 231 { | 239 { |
| 232 typedef typename Deque<T, inlineCapacity, Allocator>::const_iterator ite rator; | 240 typedef typename Deque<T, inlineCapacity, Allocator>::const_iterator ite rator; |
| 233 iterator end = collection.end(); | 241 iterator end = collection.end(); |
| 234 for (iterator it = collection.begin(); it != end; ++it) | 242 for (iterator it = collection.begin(); it != end; ++it) |
| 235 delete *it; | 243 delete *it; |
| 236 } | 244 } |
| 237 | 245 |
| 238 template<typename T, size_t inlineCapacity, typename Allocator> | 246 template<typename T, size_t inlineCapacity, typename Allocator> |
| 239 inline Deque<T, 0, Allocator>& Deque<T, inlineCapacity, Allocator>::operator =(const Deque& other) | 247 inline Deque<T, inlineCapacity, Allocator>& Deque<T, inlineCapacity, Allocat or>::operator=(const Deque& other) |
| 240 { | 248 { |
| 241 Deque<T> copy(other); | 249 Deque copy(other); |
| 242 swap(copy); | 250 swap(copy); |
| 243 return *this; | 251 return *this; |
| 244 } | 252 } |
| 245 | 253 |
| 246 template<typename T, size_t inlineCapacity, typename Allocator> | 254 template<typename T, size_t inlineCapacity, typename Allocator> |
| 247 inline void Deque<T, inlineCapacity, Allocator>::destroyAll() | 255 inline void Deque<T, inlineCapacity, Allocator>::destroyAll() |
| 248 { | 256 { |
| 249 if (m_start <= m_end) { | 257 if (m_start <= m_end) { |
| 250 TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffe r() + m_end); | 258 TypeOperations::destruct(buffer() + m_start, buffer() + m_end); |
| 251 m_buffer.clearUnusedSlots(m_buffer.buffer() + m_start, m_buffer.buff er() + m_end); | 259 clearUnusedSlots(buffer() + m_start, buffer() + m_end); |
| 252 } else { | 260 } else { |
| 253 TypeOperations::destruct(m_buffer.buffer(), m_buffer.buffer() + m_en d); | 261 TypeOperations::destruct(buffer(), buffer() + m_end); |
| 254 m_buffer.clearUnusedSlots(m_buffer.buffer(), m_buffer.buffer() + m_e nd); | 262 clearUnusedSlots(buffer(), buffer() + m_end); |
| 255 TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffe r() + m_buffer.capacity()); | 263 TypeOperations::destruct(buffer() + m_start, buffer() + capacity()); |
| 256 m_buffer.clearUnusedSlots(m_buffer.buffer() + m_start, m_buffer.buff er() + m_buffer.capacity()); | 264 clearUnusedSlots(buffer() + m_start, buffer() + capacity()); |
| 257 } | 265 } |
| 258 } | 266 } |
| 259 | 267 |
| 260 // Off-GC-heap deques: Destructor should be called. | 268 // Off-GC-heap deques: Destructor should be called. |
| 261 // On-GC-heap deques: Destructor should be called for inline buffers | 269 // On-GC-heap deques: Destructor should be called for inline buffers |
| 262 // (if any) but destructor shouldn't be called for vector backing since | 270 // (if any) but destructor shouldn't be called for vector backing since |
| 263 // it is managed by the traced GC heap. | 271 // it is managed by the traced GC heap. |
| 264 template<typename T, size_t inlineCapacity, typename Allocator> | 272 template<typename T, size_t inlineCapacity, typename Allocator> |
| 265 inline void Deque<T, inlineCapacity, Allocator>::finalize() | 273 inline void Deque<T, inlineCapacity, Allocator>::finalize() |
| 266 { | 274 { |
| 267 if (!inlineCapacity && !m_buffer.buffer()) | 275 if (!inlineCapacity && !buffer()) |
| 268 return; | 276 return; |
| 269 if (!isEmpty() && !(Allocator::isGarbageCollected && m_buffer.hasOutOfLi neBuffer())) | 277 if (!isEmpty() && !(Allocator::isGarbageCollected && hasOutOfLineBuffer( ))) |
| 270 destroyAll(); | 278 destroyAll(); |
| 271 | 279 |
| 272 m_buffer.destruct(); | 280 Base::destruct(); |
| 273 } | |
| 274 | |
| 275 // FIXME: Doesn't work if there is an inline buffer, due to crbug.com/360572 | |
| 276 template<typename T, size_t inlineCapacity, typename Allocator> | |
| 277 inline void Deque<T, inlineCapacity, Allocator>::swap(Deque<T, 0, Allocator> & other) | |
| 278 { | |
| 279 std::swap(m_start, other.m_start); | |
| 280 std::swap(m_end, other.m_end); | |
| 281 m_buffer.swapVectorBuffer(other.m_buffer); | |
| 282 } | 281 } |
| 283 | 282 |
| 284 template<typename T, size_t inlineCapacity, typename Allocator> | 283 template<typename T, size_t inlineCapacity, typename Allocator> |
| 284 inline void Deque<T, inlineCapacity, Allocator>::swap(Deque<T, inlineCapacit y, Allocator>& other) | |
| 285 { | |
| 286 Range thisRange = (m_start != m_end && m_end == 0) ? Range(m_start, capa city()) : Range(m_start, m_end); | |
| 287 Range otherRange = (other.m_start != other.m_end && other.m_end == 0) ? Range(other.m_start, capacity()) : Range(other.m_start, other.m_end); | |
|
Ken Russell (switch to Gerrit)
2014/07/16 07:38:42
It's legal to use capacity() with other because in
Erik Corry
2014/07/17 12:40:04
No that was wrong, nice catch, poor tests!
| |
| 288 Base::swapVectorBuffer(other, thisRange, otherRange); | |
| 289 std::swap(m_start, other.m_start); | |
| 290 std::swap(m_end, other.m_end); | |
| 291 } | |
| 292 | |
| 293 template<typename T, size_t inlineCapacity, typename Allocator> | |
| 285 inline void Deque<T, inlineCapacity, Allocator>::clear() | 294 inline void Deque<T, inlineCapacity, Allocator>::clear() |
| 286 { | 295 { |
| 287 destroyAll(); | 296 destroyAll(); |
| 288 m_start = 0; | 297 m_start = 0; |
| 289 m_end = 0; | 298 m_end = 0; |
| 290 m_buffer.deallocateBuffer(m_buffer.buffer()); | 299 Base::deallocateBuffer(buffer()); |
| 291 m_buffer.resetBufferPointer(); | 300 Base::resetBufferPointer(); |
| 292 } | 301 } |
| 293 | 302 |
| 294 template<typename T, size_t inlineCapacity, typename Allocator> | 303 template<typename T, size_t inlineCapacity, typename Allocator> |
| 295 template<typename Predicate> | 304 template<typename Predicate> |
| 296 inline DequeIterator<T, inlineCapacity, Allocator> Deque<T, inlineCapacity, Allocator>::findIf(Predicate& predicate) | 305 inline DequeIterator<T, inlineCapacity, Allocator> Deque<T, inlineCapacity, Allocator>::findIf(Predicate& predicate) |
| 297 { | 306 { |
| 298 iterator end_iterator = end(); | 307 iterator end_iterator = end(); |
| 299 for (iterator it = begin(); it != end_iterator; ++it) { | 308 for (iterator it = begin(); it != end_iterator; ++it) { |
| 300 if (predicate(*it)) | 309 if (predicate(*it)) |
| 301 return it; | 310 return it; |
| 302 } | 311 } |
| 303 return end_iterator; | 312 return end_iterator; |
| 304 } | 313 } |
| 305 | 314 |
| 315 // Because start == end indicates an empty deque, we can never use the last | |
| 316 // element in the backing. | |
| 306 template<typename T, size_t inlineCapacity, typename Allocator> | 317 template<typename T, size_t inlineCapacity, typename Allocator> |
| 307 inline void Deque<T, inlineCapacity, Allocator>::expandCapacityIfNeeded() | 318 inline void Deque<T, inlineCapacity, Allocator>::expandCapacityIfNeeded() |
| 308 { | 319 { |
| 309 if (m_start) { | 320 if (m_start) { |
| 310 if (m_end + 1 != m_start) | 321 if (m_end + 1 != m_start) |
| 311 return; | 322 return; |
| 312 } else if (m_end) { | 323 } else if (m_end) { |
| 313 if (m_end != m_buffer.capacity() - 1) | 324 if (m_end != capacity() - 1) |
| 314 return; | 325 return; |
| 315 } else if (m_buffer.capacity()) | 326 } else if (capacity()) |
| 316 return; | 327 return; |
| 317 | 328 |
| 318 expandCapacity(); | 329 expandCapacity(); |
| 319 } | 330 } |
| 320 | 331 |
| 321 template<typename T, size_t inlineCapacity, typename Allocator> | 332 template<typename T, size_t inlineCapacity, typename Allocator> |
| 322 void Deque<T, inlineCapacity, Allocator>::expandCapacity() | 333 void Deque<T, inlineCapacity, Allocator>::expandCapacity() |
| 323 { | 334 { |
| 324 size_t oldCapacity = m_buffer.capacity(); | 335 size_t oldCapacity = capacity(); |
| 325 T* oldBuffer = m_buffer.buffer(); | 336 T* oldBuffer = buffer(); |
| 326 m_buffer.allocateBuffer(std::max(static_cast<size_t>(16), oldCapacity + oldCapacity / 4 + 1)); | 337 Base::allocateBuffer(std::max(static_cast<size_t>(16), oldCapacity + old Capacity / 4 + 1)); |
| 327 if (m_start <= m_end) | 338 if (m_start <= m_end) |
| 328 TypeOperations::move(oldBuffer + m_start, oldBuffer + m_end, m_buffe r.buffer() + m_start); | 339 TypeOperations::move(oldBuffer + m_start, oldBuffer + m_end, buffer( ) + m_start); |
| 329 else { | 340 else { |
| 330 TypeOperations::move(oldBuffer, oldBuffer + m_end, m_buffer.buffer() ); | 341 TypeOperations::move(oldBuffer, oldBuffer + m_end, buffer()); |
| 331 size_t newStart = m_buffer.capacity() - (oldCapacity - m_start); | 342 size_t newStart = capacity() - (oldCapacity - m_start); |
| 332 TypeOperations::move(oldBuffer + m_start, oldBuffer + oldCapacity, m _buffer.buffer() + newStart); | 343 TypeOperations::move(oldBuffer + m_start, oldBuffer + oldCapacity, b uffer() + newStart); |
| 333 m_start = newStart; | 344 m_start = newStart; |
| 334 } | 345 } |
| 335 m_buffer.deallocateBuffer(oldBuffer); | 346 Base::deallocateBuffer(oldBuffer); |
| 336 } | 347 } |
| 337 | 348 |
| 338 template<typename T, size_t inlineCapacity, typename Allocator> | 349 template<typename T, size_t inlineCapacity, typename Allocator> |
| 339 inline typename Deque<T, inlineCapacity, Allocator>::PassType Deque<T, inlin eCapacity, Allocator>::takeFirst() | 350 inline typename Deque<T, inlineCapacity, Allocator>::PassType Deque<T, inlin eCapacity, Allocator>::takeFirst() |
| 340 { | 351 { |
| 341 T oldFirst = Pass::transfer(first()); | 352 T oldFirst = Pass::transfer(first()); |
| 342 removeFirst(); | 353 removeFirst(); |
| 343 return Pass::transfer(oldFirst); | 354 return Pass::transfer(oldFirst); |
| 344 } | 355 } |
| 345 | 356 |
| 346 template<typename T, size_t inlineCapacity, typename Allocator> | 357 template<typename T, size_t inlineCapacity, typename Allocator> |
| 347 inline typename Deque<T, inlineCapacity, Allocator>::PassType Deque<T, inlin eCapacity, Allocator>::takeLast() | 358 inline typename Deque<T, inlineCapacity, Allocator>::PassType Deque<T, inlin eCapacity, Allocator>::takeLast() |
| 348 { | 359 { |
| 349 T oldLast = Pass::transfer(last()); | 360 T oldLast = Pass::transfer(last()); |
| 350 removeLast(); | 361 removeLast(); |
| 351 return Pass::transfer(oldLast); | 362 return Pass::transfer(oldLast); |
| 352 } | 363 } |
| 353 | 364 |
| 354 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 365 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
| 355 inline void Deque<T, inlineCapacity, Allocator>::append(const U& value) | 366 inline void Deque<T, inlineCapacity, Allocator>::append(const U& value) |
| 356 { | 367 { |
| 357 expandCapacityIfNeeded(); | 368 expandCapacityIfNeeded(); |
| 358 new (NotNull, &m_buffer.buffer()[m_end]) T(value); | 369 new (NotNull, &buffer()[m_end]) T(value); |
| 359 if (m_end == m_buffer.capacity() - 1) | 370 if (m_end == capacity() - 1) |
| 360 m_end = 0; | 371 m_end = 0; |
| 361 else | 372 else |
| 362 ++m_end; | 373 ++m_end; |
| 363 } | 374 } |
| 364 | 375 |
| 365 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 376 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
| 366 inline void Deque<T, inlineCapacity, Allocator>::prepend(const U& value) | 377 inline void Deque<T, inlineCapacity, Allocator>::prepend(const U& value) |
| 367 { | 378 { |
| 368 expandCapacityIfNeeded(); | 379 expandCapacityIfNeeded(); |
| 369 if (!m_start) | 380 if (!m_start) |
| 370 m_start = m_buffer.capacity() - 1; | 381 m_start = capacity() - 1; |
| 371 else | 382 else |
| 372 --m_start; | 383 --m_start; |
| 373 new (NotNull, &m_buffer.buffer()[m_start]) T(value); | 384 new (NotNull, &buffer()[m_start]) T(value); |
| 374 } | 385 } |
| 375 | 386 |
| 376 template<typename T, size_t inlineCapacity, typename Allocator> | 387 template<typename T, size_t inlineCapacity, typename Allocator> |
| 377 inline void Deque<T, inlineCapacity, Allocator>::removeFirst() | 388 inline void Deque<T, inlineCapacity, Allocator>::removeFirst() |
| 378 { | 389 { |
| 379 ASSERT(!isEmpty()); | 390 ASSERT(!isEmpty()); |
| 380 TypeOperations::destruct(&m_buffer.buffer()[m_start], &m_buffer.buffer() [m_start + 1]); | 391 TypeOperations::destruct(&buffer()[m_start], &buffer()[m_start + 1]); |
| 381 m_buffer.clearUnusedSlots(&m_buffer.buffer()[m_start], &m_buffer.buffer( )[m_start + 1]); | 392 clearUnusedSlots(&buffer()[m_start], &buffer()[m_start + 1]); |
| 382 if (m_start == m_buffer.capacity() - 1) | 393 if (m_start == capacity() - 1) |
| 383 m_start = 0; | 394 m_start = 0; |
| 384 else | 395 else |
| 385 ++m_start; | 396 ++m_start; |
| 386 } | 397 } |
| 387 | 398 |
| 388 template<typename T, size_t inlineCapacity, typename Allocator> | 399 template<typename T, size_t inlineCapacity, typename Allocator> |
| 389 inline void Deque<T, inlineCapacity, Allocator>::removeLast() | 400 inline void Deque<T, inlineCapacity, Allocator>::removeLast() |
| 390 { | 401 { |
| 391 ASSERT(!isEmpty()); | 402 ASSERT(!isEmpty()); |
| 392 if (!m_end) | 403 if (!m_end) |
| 393 m_end = m_buffer.capacity() - 1; | 404 m_end = capacity() - 1; |
| 394 else | 405 else |
| 395 --m_end; | 406 --m_end; |
| 396 TypeOperations::destruct(&m_buffer.buffer()[m_end], &m_buffer.buffer()[m _end + 1]); | 407 TypeOperations::destruct(&buffer()[m_end], &buffer()[m_end + 1]); |
| 397 m_buffer.clearUnusedSlots(&m_buffer.buffer()[m_end], &m_buffer.buffer()[ m_end + 1]); | 408 clearUnusedSlots(&buffer()[m_end], &buffer()[m_end + 1]); |
| 398 } | 409 } |
| 399 | 410 |
| 400 template<typename T, size_t inlineCapacity, typename Allocator> | 411 template<typename T, size_t inlineCapacity, typename Allocator> |
| 401 inline void Deque<T, inlineCapacity, Allocator>::remove(iterator& it) | 412 inline void Deque<T, inlineCapacity, Allocator>::remove(iterator& it) |
| 402 { | 413 { |
| 403 remove(it.m_index); | 414 remove(it.m_index); |
| 404 } | 415 } |
| 405 | 416 |
| 406 template<typename T, size_t inlineCapacity, typename Allocator> | 417 template<typename T, size_t inlineCapacity, typename Allocator> |
| 407 inline void Deque<T, inlineCapacity, Allocator>::remove(const_iterator& it) | 418 inline void Deque<T, inlineCapacity, Allocator>::remove(const_iterator& it) |
| 408 { | 419 { |
| 409 remove(it.m_index); | 420 remove(it.m_index); |
| 410 } | 421 } |
| 411 | 422 |
| 412 template<typename T, size_t inlineCapacity, typename Allocator> | 423 template<typename T, size_t inlineCapacity, typename Allocator> |
| 413 inline void Deque<T, inlineCapacity, Allocator>::remove(size_t position) | 424 inline void Deque<T, inlineCapacity, Allocator>::remove(size_t position) |
| 414 { | 425 { |
| 415 if (position == m_end) | 426 if (position == m_end) |
| 416 return; | 427 return; |
| 417 | 428 |
| 418 T* buffer = m_buffer.buffer(); | 429 T* buf = buffer(); |
| 419 TypeOperations::destruct(&buffer[position], &buffer[position + 1]); | 430 TypeOperations::destruct(&buf[position], &buf[position + 1]); |
| 420 | 431 |
| 421 // Find which segment of the circular buffer contained the remove elemen t, and only move elements in that part. | 432 // Find which segment of the circular buffer contained the remove elemen t, and only move elements in that part. |
| 422 if (position >= m_start) { | 433 if (position >= m_start) { |
| 423 TypeOperations::moveOverlapping(buffer + m_start, buffer + position, buffer + m_start + 1); | 434 TypeOperations::moveOverlapping(buf + m_start, buf + position, buf + m_start + 1); |
| 424 m_buffer.clearUnusedSlots(buffer + m_start, buffer + m_start + 1); | 435 clearUnusedSlots(buf + m_start, buf + m_start + 1); |
| 425 m_start = (m_start + 1) % m_buffer.capacity(); | 436 m_start = (m_start + 1) % capacity(); |
| 426 } else { | 437 } else { |
| 427 TypeOperations::moveOverlapping(buffer + position + 1, buffer + m_en d, buffer + position); | 438 TypeOperations::moveOverlapping(buf + position + 1, buf + m_end, buf + position); |
| 428 m_buffer.clearUnusedSlots(buffer + m_end - 1, buffer + m_end); | 439 clearUnusedSlots(buf + m_end - 1, buf + m_end); |
| 429 m_end = (m_end - 1 + m_buffer.capacity()) % m_buffer.capacity(); | 440 m_end = (m_end - 1 + capacity()) % capacity(); |
| 430 } | 441 } |
| 431 } | 442 } |
| 432 | 443 |
| 433 template<typename T, size_t inlineCapacity, typename Allocator> | 444 template<typename T, size_t inlineCapacity, typename Allocator> |
| 434 inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase() | 445 inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase() |
| 435 : m_deque(0) | 446 : m_deque(0) |
| 436 { | 447 { |
| 437 } | 448 } |
| 438 | 449 |
| 439 template<typename T, size_t inlineCapacity, typename Allocator> | 450 template<typename T, size_t inlineCapacity, typename Allocator> |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 466 template<typename T, size_t inlineCapacity, typename Allocator> | 477 template<typename T, size_t inlineCapacity, typename Allocator> |
| 467 inline bool DequeIteratorBase<T, inlineCapacity, Allocator>::isEqual(const D equeIteratorBase& other) const | 478 inline bool DequeIteratorBase<T, inlineCapacity, Allocator>::isEqual(const D equeIteratorBase& other) const |
| 468 { | 479 { |
| 469 return m_index == other.m_index; | 480 return m_index == other.m_index; |
| 470 } | 481 } |
| 471 | 482 |
| 472 template<typename T, size_t inlineCapacity, typename Allocator> | 483 template<typename T, size_t inlineCapacity, typename Allocator> |
| 473 inline void DequeIteratorBase<T, inlineCapacity, Allocator>::increment() | 484 inline void DequeIteratorBase<T, inlineCapacity, Allocator>::increment() |
| 474 { | 485 { |
| 475 ASSERT(m_index != m_deque->m_end); | 486 ASSERT(m_index != m_deque->m_end); |
| 476 ASSERT(m_deque->m_buffer.capacity()); | 487 ASSERT(m_deque->capacity()); |
| 477 if (m_index == m_deque->m_buffer.capacity() - 1) | 488 if (m_index == m_deque->capacity() - 1) |
| 478 m_index = 0; | 489 m_index = 0; |
| 479 else | 490 else |
| 480 ++m_index; | 491 ++m_index; |
| 481 } | 492 } |
| 482 | 493 |
| 483 template<typename T, size_t inlineCapacity, typename Allocator> | 494 template<typename T, size_t inlineCapacity, typename Allocator> |
| 484 inline void DequeIteratorBase<T, inlineCapacity, Allocator>::decrement() | 495 inline void DequeIteratorBase<T, inlineCapacity, Allocator>::decrement() |
| 485 { | 496 { |
| 486 ASSERT(m_index != m_deque->m_start); | 497 ASSERT(m_index != m_deque->m_start); |
| 487 ASSERT(m_deque->m_buffer.capacity()); | 498 ASSERT(m_deque->capacity()); |
| 488 if (!m_index) | 499 if (!m_index) |
| 489 m_index = m_deque->m_buffer.capacity() - 1; | 500 m_index = m_deque->capacity() - 1; |
| 490 else | 501 else |
| 491 --m_index; | 502 --m_index; |
| 492 } | 503 } |
| 493 | 504 |
| 494 template<typename T, size_t inlineCapacity, typename Allocator> | 505 template<typename T, size_t inlineCapacity, typename Allocator> |
| 495 inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::after() const | 506 inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::after() const |
| 496 { | 507 { |
| 497 ASSERT(m_index != m_deque->m_end); | 508 ASSERT(m_index != m_deque->m_end); |
| 498 return &m_deque->m_buffer.buffer()[m_index]; | 509 return &m_deque->buffer()[m_index]; |
| 499 } | 510 } |
| 500 | 511 |
| 501 template<typename T, size_t inlineCapacity, typename Allocator> | 512 template<typename T, size_t inlineCapacity, typename Allocator> |
| 502 inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::before() const | 513 inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::before() const |
| 503 { | 514 { |
| 504 ASSERT(m_index != m_deque->m_start); | 515 ASSERT(m_index != m_deque->m_start); |
| 505 if (!m_index) | 516 if (!m_index) |
| 506 return &m_deque->m_buffer.buffer()[m_deque->m_buffer.capacity() - 1] ; | 517 return &m_deque->buffer()[m_deque->capacity() - 1]; |
| 507 return &m_deque->m_buffer.buffer()[m_index - 1]; | 518 return &m_deque->buffer()[m_index - 1]; |
| 508 } | 519 } |
| 509 | 520 |
| 510 // This is only called if the allocator is a HeapAllocator. It is used when | 521 // This is only called if the allocator is a HeapAllocator. It is used when |
| 511 // visiting during a tracing GC. | 522 // visiting during a tracing GC. |
| 512 template<typename T, size_t inlineCapacity, typename Allocator> | 523 template<typename T, size_t inlineCapacity, typename Allocator> |
| 513 void Deque<T, inlineCapacity, Allocator>::trace(typename Allocator::Visitor* visitor) | 524 void Deque<T, inlineCapacity, Allocator>::trace(typename Allocator::Visitor* visitor) |
| 514 { | 525 { |
| 515 ASSERT(Allocator::isGarbageCollected); // Garbage collector must be enab led. | 526 ASSERT(Allocator::isGarbageCollected); // Garbage collector must be enab led. |
| 516 const T* bufferBegin = m_buffer.buffer(); | 527 const T* bufferBegin = buffer(); |
| 517 const T* end = bufferBegin + m_end; | 528 const T* end = bufferBegin + m_end; |
| 518 if (ShouldBeTraced<VectorTraits<T> >::value) { | 529 if (ShouldBeTraced<VectorTraits<T> >::value) { |
| 519 if (m_start <= m_end) { | 530 if (m_start <= m_end) { |
| 520 for (const T* bufferEntry = bufferBegin + m_start; bufferEntry ! = end; bufferEntry++) | 531 for (const T* bufferEntry = bufferBegin + m_start; bufferEntry ! = end; bufferEntry++) |
| 521 Allocator::template trace<T, VectorTraits<T> >(visitor, *con st_cast<T*>(bufferEntry)); | 532 Allocator::template trace<T, VectorTraits<T> >(visitor, *con st_cast<T*>(bufferEntry)); |
| 522 } else { | 533 } else { |
| 523 for (const T* bufferEntry = bufferBegin; bufferEntry != end; buf ferEntry++) | 534 for (const T* bufferEntry = bufferBegin; bufferEntry != end; buf ferEntry++) |
| 524 Allocator::template trace<T, VectorTraits<T> >(visitor, *con st_cast<T*>(bufferEntry)); | 535 Allocator::template trace<T, VectorTraits<T> >(visitor, *con st_cast<T*>(bufferEntry)); |
| 525 const T* bufferEnd = m_buffer.buffer() + m_buffer.capacity(); | 536 const T* bufferEnd = buffer() + capacity(); |
| 526 for (const T* bufferEntry = bufferBegin + m_start; bufferEntry ! = bufferEnd; bufferEntry++) | 537 for (const T* bufferEntry = bufferBegin + m_start; bufferEntry ! = bufferEnd; bufferEntry++) |
| 527 Allocator::template trace<T, VectorTraits<T> >(visitor, *con st_cast<T*>(bufferEntry)); | 538 Allocator::template trace<T, VectorTraits<T> >(visitor, *con st_cast<T*>(bufferEntry)); |
| 528 } | 539 } |
| 529 } | 540 } |
| 530 if (m_buffer.hasOutOfLineBuffer()) | 541 if (hasOutOfLineBuffer()) |
| 531 Allocator::markNoTracing(visitor, m_buffer.buffer()); | 542 Allocator::markNoTracing(visitor, buffer()); |
| 532 } | 543 } |
| 533 | 544 |
| 534 #if !ENABLE(OILPAN) | 545 #if !ENABLE(OILPAN) |
| 535 template<typename T, size_t N> | 546 template<typename T, size_t N> |
| 536 struct NeedsTracing<Deque<T, N> > { | 547 struct NeedsTracing<Deque<T, N> > { |
| 537 static const bool value = false; | 548 static const bool value = false; |
| 538 }; | 549 }; |
| 539 #endif | 550 #endif |
| 540 | 551 |
| 541 } // namespace WTF | 552 } // namespace WTF |
| 542 | 553 |
| 543 using WTF::Deque; | 554 using WTF::Deque; |
| 544 | 555 |
| 545 #endif // WTF_Deque_h | 556 #endif // WTF_Deque_h |
| OLD | NEW |