Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(493)

Side by Side Diff: third_party/WebKit/Source/wtf/Deque.h

Issue 2769603002: Move files in wtf/ to platform/wtf/ (Part 8). (Closed)
Patch Set: Rebase. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be
3 * Copyright (C) 2009 Google Inc. All rights reserved. 3 // found in the LICENSE file.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 4
30 #ifndef WTF_Deque_h 5 #include "platform/wtf/Deque.h"
31 #define WTF_Deque_h
32 6
33 // FIXME: Could move what Vector and Deque share into a separate file. 7 // The contents of this header was moved to platform/wtf as part of
34 // Deque doesn't actually use Vector. 8 // WTF migration project. See the following post for details:
35 9 // https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gY CAAJ
36 #include "wtf/Vector.h"
37 #include <iterator>
38
39 namespace WTF {
40
41 template <typename T, size_t inlineCapacity, typename Allocator>
42 class DequeIteratorBase;
43 template <typename T, size_t inlineCapacity, typename Allocator>
44 class DequeIterator;
45 template <typename T, size_t inlineCapacity, typename Allocator>
46 class DequeConstIterator;
47
48 template <typename T,
49 size_t inlineCapacity = 0,
50 typename Allocator = PartitionAllocator>
51 class Deque : public ConditionalDestructor<Deque<T, INLINE_CAPACITY, Allocator>,
52 (INLINE_CAPACITY == 0) &&
53 Allocator::isGarbageCollected> {
54 USE_ALLOCATOR(Deque, Allocator);
55
56 public:
57 typedef DequeIterator<T, inlineCapacity, Allocator> iterator;
58 typedef DequeConstIterator<T, inlineCapacity, Allocator> const_iterator;
59 typedef std::reverse_iterator<iterator> reverse_iterator;
60 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
61
62 Deque();
63 Deque(const Deque&);
64 Deque& operator=(const Deque&);
65 Deque(Deque&&);
66 Deque& operator=(Deque&&);
67
68 void finalize();
69 void finalizeGarbageCollectedObject() { finalize(); }
70
71 void swap(Deque&);
72
73 size_t size() const {
74 return m_start <= m_end ? m_end - m_start
75 : m_end + m_buffer.capacity() - m_start;
76 }
77 bool isEmpty() const { return m_start == m_end; }
78
79 iterator begin() { return iterator(this, m_start); }
80 iterator end() { return iterator(this, m_end); }
81 const_iterator begin() const { return const_iterator(this, m_start); }
82 const_iterator end() const { return const_iterator(this, m_end); }
83 reverse_iterator rbegin() { return reverse_iterator(end()); }
84 reverse_iterator rend() { return reverse_iterator(begin()); }
85 const_reverse_iterator rbegin() const {
86 return const_reverse_iterator(end());
87 }
88 const_reverse_iterator rend() const {
89 return const_reverse_iterator(begin());
90 }
91
92 T& front() {
93 DCHECK_NE(m_start, m_end);
94 return m_buffer.buffer()[m_start];
95 }
96 const T& front() const {
97 DCHECK_NE(m_start, m_end);
98 return m_buffer.buffer()[m_start];
99 }
100 T takeFirst();
101
102 T& back() {
103 DCHECK_NE(m_start, m_end);
104 return *(--end());
105 }
106 const T& back() const {
107 DCHECK_NE(m_start, m_end);
108 return *(--end());
109 }
110 T takeLast();
111
112 T& at(size_t i) {
113 RELEASE_ASSERT(i < size());
114 size_t right = m_buffer.capacity() - m_start;
115 return i < right ? m_buffer.buffer()[m_start + i]
116 : m_buffer.buffer()[i - right];
117 }
118 const T& at(size_t i) const {
119 RELEASE_ASSERT(i < size());
120 size_t right = m_buffer.capacity() - m_start;
121 return i < right ? m_buffer.buffer()[m_start + i]
122 : m_buffer.buffer()[i - right];
123 }
124
125 T& operator[](size_t i) { return at(i); }
126 const T& operator[](size_t i) const { return at(i); }
127
128 template <typename U>
129 void push_front(U&&);
130 void erase(iterator&);
131 void erase(const_iterator&);
132
133 // STL compatibility.
134 template <typename U>
135 void push_back(U&&);
136 void pop_back();
137 void pop_front();
138 bool empty() const { return isEmpty(); }
139 template <typename... Args>
140 void emplace_back(Args&&...);
141 template <typename... Args>
142 void emplace_front(Args&&...);
143
144 void clear();
145
146 template <typename VisitorDispatcher>
147 void trace(VisitorDispatcher);
148
149 static_assert(!std::is_polymorphic<T>::value ||
150 !VectorTraits<T>::canInitializeWithMemset,
151 "Cannot initialize with memset if there is a vtable");
152 static_assert(Allocator::isGarbageCollected ||
153 !AllowsOnlyPlacementNew<T>::value ||
154 !IsTraceable<T>::value,
155 "Cannot put DISALLOW_NEW_EXCEPT_PLACEMENT_NEW objects that "
156 "have trace methods into an off-heap Deque");
157 static_assert(Allocator::isGarbageCollected ||
158 !IsPointerToGarbageCollectedType<T>::value,
159 "Cannot put raw pointers to garbage-collected classes into a "
160 "Deque. Use HeapDeque<Member<T>> instead.");
161
162 private:
163 friend class DequeIteratorBase<T, inlineCapacity, Allocator>;
164
165 class BackingBuffer : public VectorBuffer<T, INLINE_CAPACITY, Allocator> {
166 WTF_MAKE_NONCOPYABLE(BackingBuffer);
167
168 private:
169 using Base = VectorBuffer<T, INLINE_CAPACITY, Allocator>;
170 using Base::m_size;
171
172 public:
173 BackingBuffer() : Base() {}
174 explicit BackingBuffer(size_t capacity) : Base(capacity) {}
175
176 void setSize(size_t size) { m_size = size; }
177 };
178
179 typedef VectorTypeOperations<T> TypeOperations;
180 typedef DequeIteratorBase<T, inlineCapacity, Allocator> IteratorBase;
181
182 void erase(size_t position);
183 void destroyAll();
184 void expandCapacityIfNeeded();
185 void expandCapacity();
186
187 BackingBuffer m_buffer;
188 unsigned m_start;
189 unsigned m_end;
190 };
191
192 template <typename T, size_t inlineCapacity, typename Allocator>
193 class DequeIteratorBase {
194 DISALLOW_NEW();
195
196 protected:
197 DequeIteratorBase();
198 DequeIteratorBase(const Deque<T, inlineCapacity, Allocator>*, size_t);
199 DequeIteratorBase(const DequeIteratorBase&);
200 DequeIteratorBase& operator=(const DequeIteratorBase<T, 0, Allocator>&);
201 ~DequeIteratorBase();
202
203 void assign(const DequeIteratorBase& other) { *this = other; }
204
205 void increment();
206 void decrement();
207
208 T* before() const;
209 T* after() const;
210
211 bool isEqual(const DequeIteratorBase&) const;
212
213 private:
214 Deque<T, inlineCapacity, Allocator>* m_deque;
215 unsigned m_index;
216
217 friend class Deque<T, inlineCapacity, Allocator>;
218 };
219
220 template <typename T,
221 size_t inlineCapacity = 0,
222 typename Allocator = PartitionAllocator>
223 class DequeIterator : public DequeIteratorBase<T, inlineCapacity, Allocator> {
224 private:
225 typedef DequeIteratorBase<T, inlineCapacity, Allocator> Base;
226 typedef DequeIterator<T, inlineCapacity, Allocator> Iterator;
227
228 public:
229 typedef ptrdiff_t difference_type;
230 typedef T value_type;
231 typedef T* pointer;
232 typedef T& reference;
233 typedef std::bidirectional_iterator_tag iterator_category;
234
235 DequeIterator(Deque<T, inlineCapacity, Allocator>* deque, size_t index)
236 : Base(deque, index) {}
237
238 DequeIterator(const Iterator& other) : Base(other) {}
239 DequeIterator& operator=(const Iterator& other) {
240 Base::assign(other);
241 return *this;
242 }
243
244 T& operator*() const { return *Base::after(); }
245 T* operator->() const { return Base::after(); }
246
247 bool operator==(const Iterator& other) const { return Base::isEqual(other); }
248 bool operator!=(const Iterator& other) const { return !Base::isEqual(other); }
249
250 Iterator& operator++() {
251 Base::increment();
252 return *this;
253 }
254 // postfix ++ intentionally omitted
255 Iterator& operator--() {
256 Base::decrement();
257 return *this;
258 }
259 // postfix -- intentionally omitted
260 };
261
262 template <typename T,
263 size_t inlineCapacity = 0,
264 typename Allocator = PartitionAllocator>
265 class DequeConstIterator
266 : public DequeIteratorBase<T, inlineCapacity, Allocator> {
267 private:
268 typedef DequeIteratorBase<T, inlineCapacity, Allocator> Base;
269 typedef DequeConstIterator<T, inlineCapacity, Allocator> Iterator;
270 typedef DequeIterator<T, inlineCapacity, Allocator> NonConstIterator;
271
272 public:
273 typedef ptrdiff_t difference_type;
274 typedef T value_type;
275 typedef const T* pointer;
276 typedef const T& reference;
277 typedef std::bidirectional_iterator_tag iterator_category;
278
279 DequeConstIterator(const Deque<T, inlineCapacity, Allocator>* deque,
280 size_t index)
281 : Base(deque, index) {}
282
283 DequeConstIterator(const Iterator& other) : Base(other) {}
284 DequeConstIterator(const NonConstIterator& other) : Base(other) {}
285 DequeConstIterator& operator=(const Iterator& other) {
286 Base::assign(other);
287 return *this;
288 }
289 DequeConstIterator& operator=(const NonConstIterator& other) {
290 Base::assign(other);
291 return *this;
292 }
293
294 const T& operator*() const { return *Base::after(); }
295 const T* operator->() const { return Base::after(); }
296
297 bool operator==(const Iterator& other) const { return Base::isEqual(other); }
298 bool operator!=(const Iterator& other) const { return !Base::isEqual(other); }
299
300 Iterator& operator++() {
301 Base::increment();
302 return *this;
303 }
304 // postfix ++ intentionally omitted
305 Iterator& operator--() {
306 Base::decrement();
307 return *this;
308 }
309 // postfix -- intentionally omitted
310 };
311
312 template <typename T, size_t inlineCapacity, typename Allocator>
313 inline Deque<T, inlineCapacity, Allocator>::Deque() : m_start(0), m_end(0) {}
314
315 template <typename T, size_t inlineCapacity, typename Allocator>
316 inline Deque<T, inlineCapacity, Allocator>::Deque(const Deque& other)
317 : m_buffer(other.m_buffer.capacity()),
318 m_start(other.m_start),
319 m_end(other.m_end) {
320 const T* otherBuffer = other.m_buffer.buffer();
321 if (m_start <= m_end) {
322 TypeOperations::uninitializedCopy(otherBuffer + m_start,
323 otherBuffer + m_end,
324 m_buffer.buffer() + m_start);
325 } else {
326 TypeOperations::uninitializedCopy(otherBuffer, otherBuffer + m_end,
327 m_buffer.buffer());
328 TypeOperations::uninitializedCopy(otherBuffer + m_start,
329 otherBuffer + m_buffer.capacity(),
330 m_buffer.buffer() + m_start);
331 }
332 }
333
334 template <typename T, size_t inlineCapacity, typename Allocator>
335 inline Deque<T, inlineCapacity, Allocator>&
336 Deque<T, inlineCapacity, Allocator>::operator=(const Deque& other) {
337 Deque<T> copy(other);
338 swap(copy);
339 return *this;
340 }
341
342 template <typename T, size_t inlineCapacity, typename Allocator>
343 inline Deque<T, inlineCapacity, Allocator>::Deque(Deque&& other)
344 : m_start(0), m_end(0) {
345 swap(other);
346 }
347
348 template <typename T, size_t inlineCapacity, typename Allocator>
349 inline Deque<T, inlineCapacity, Allocator>&
350 Deque<T, inlineCapacity, Allocator>::operator=(Deque&& other) {
351 swap(other);
352 return *this;
353 }
354
355 template <typename T, size_t inlineCapacity, typename Allocator>
356 inline void Deque<T, inlineCapacity, Allocator>::destroyAll() {
357 if (m_start <= m_end) {
358 TypeOperations::destruct(m_buffer.buffer() + m_start,
359 m_buffer.buffer() + m_end);
360 m_buffer.clearUnusedSlots(m_buffer.buffer() + m_start,
361 m_buffer.buffer() + m_end);
362 } else {
363 TypeOperations::destruct(m_buffer.buffer(), m_buffer.buffer() + m_end);
364 m_buffer.clearUnusedSlots(m_buffer.buffer(), m_buffer.buffer() + m_end);
365 TypeOperations::destruct(m_buffer.buffer() + m_start,
366 m_buffer.buffer() + m_buffer.capacity());
367 m_buffer.clearUnusedSlots(m_buffer.buffer() + m_start,
368 m_buffer.buffer() + m_buffer.capacity());
369 }
370 }
371
372 // Off-GC-heap deques: Destructor should be called.
373 // On-GC-heap deques: Destructor should be called for inline buffers (if any)
374 // but destructor shouldn't be called for vector backing since it is managed by
375 // the traced GC heap.
376 template <typename T, size_t inlineCapacity, typename Allocator>
377 inline void Deque<T, inlineCapacity, Allocator>::finalize() {
378 if (!INLINE_CAPACITY && !m_buffer.buffer())
379 return;
380 if (!isEmpty() &&
381 !(Allocator::isGarbageCollected && m_buffer.hasOutOfLineBuffer()))
382 destroyAll();
383
384 m_buffer.destruct();
385 }
386
387 template <typename T, size_t inlineCapacity, typename Allocator>
388 inline void Deque<T, inlineCapacity, Allocator>::swap(Deque& other) {
389 typename BackingBuffer::OffsetRange thisHole;
390 if (m_start <= m_end) {
391 m_buffer.setSize(m_end);
392 thisHole.begin = 0;
393 thisHole.end = m_start;
394 } else {
395 m_buffer.setSize(m_buffer.capacity());
396 thisHole.begin = m_end;
397 thisHole.end = m_start;
398 }
399 typename BackingBuffer::OffsetRange otherHole;
400 if (other.m_start <= other.m_end) {
401 other.m_buffer.setSize(other.m_end);
402 otherHole.begin = 0;
403 otherHole.end = other.m_start;
404 } else {
405 other.m_buffer.setSize(other.m_buffer.capacity());
406 otherHole.begin = other.m_end;
407 otherHole.end = other.m_start;
408 }
409
410 m_buffer.swapVectorBuffer(other.m_buffer, thisHole, otherHole);
411
412 std::swap(m_start, other.m_start);
413 std::swap(m_end, other.m_end);
414 }
415
416 template <typename T, size_t inlineCapacity, typename Allocator>
417 inline void Deque<T, inlineCapacity, Allocator>::clear() {
418 destroyAll();
419 m_start = 0;
420 m_end = 0;
421 m_buffer.deallocateBuffer(m_buffer.buffer());
422 m_buffer.resetBufferPointer();
423 }
424
425 template <typename T, size_t inlineCapacity, typename Allocator>
426 inline void Deque<T, inlineCapacity, Allocator>::expandCapacityIfNeeded() {
427 if (m_start) {
428 if (m_end + 1 != m_start)
429 return;
430 } else if (m_end) {
431 if (m_end != m_buffer.capacity() - 1)
432 return;
433 } else if (m_buffer.capacity()) {
434 return;
435 }
436
437 expandCapacity();
438 }
439
440 template <typename T, size_t inlineCapacity, typename Allocator>
441 void Deque<T, inlineCapacity, Allocator>::expandCapacity() {
442 size_t oldCapacity = m_buffer.capacity();
443 T* oldBuffer = m_buffer.buffer();
444 size_t newCapacity =
445 std::max(static_cast<size_t>(16), oldCapacity + oldCapacity / 4 + 1);
446 if (m_buffer.expandBuffer(newCapacity)) {
447 if (m_start <= m_end) {
448 // No adjustments to be done.
449 } else {
450 size_t newStart = m_buffer.capacity() - (oldCapacity - m_start);
451 TypeOperations::moveOverlapping(oldBuffer + m_start,
452 oldBuffer + oldCapacity,
453 m_buffer.buffer() + newStart);
454 m_buffer.clearUnusedSlots(oldBuffer + m_start,
455 oldBuffer + std::min(oldCapacity, newStart));
456 m_start = newStart;
457 }
458 return;
459 }
460 m_buffer.allocateBuffer(newCapacity);
461 if (m_start <= m_end) {
462 TypeOperations::move(oldBuffer + m_start, oldBuffer + m_end,
463 m_buffer.buffer() + m_start);
464 m_buffer.clearUnusedSlots(oldBuffer + m_start, oldBuffer + m_end);
465 } else {
466 TypeOperations::move(oldBuffer, oldBuffer + m_end, m_buffer.buffer());
467 m_buffer.clearUnusedSlots(oldBuffer, oldBuffer + m_end);
468 size_t newStart = m_buffer.capacity() - (oldCapacity - m_start);
469 TypeOperations::move(oldBuffer + m_start, oldBuffer + oldCapacity,
470 m_buffer.buffer() + newStart);
471 m_buffer.clearUnusedSlots(oldBuffer + m_start, oldBuffer + oldCapacity);
472 m_start = newStart;
473 }
474 m_buffer.deallocateBuffer(oldBuffer);
475 }
476
477 template <typename T, size_t inlineCapacity, typename Allocator>
478 inline T Deque<T, inlineCapacity, Allocator>::takeFirst() {
479 T oldFirst = std::move(front());
480 pop_front();
481 return oldFirst;
482 }
483
484 template <typename T, size_t inlineCapacity, typename Allocator>
485 inline T Deque<T, inlineCapacity, Allocator>::takeLast() {
486 T oldLast = std::move(back());
487 pop_back();
488 return oldLast;
489 }
490
491 template <typename T, size_t inlineCapacity, typename Allocator>
492 template <typename U>
493 inline void Deque<T, inlineCapacity, Allocator>::push_back(U&& value) {
494 expandCapacityIfNeeded();
495 T* newElement = &m_buffer.buffer()[m_end];
496 if (m_end == m_buffer.capacity() - 1)
497 m_end = 0;
498 else
499 ++m_end;
500 new (NotNull, newElement) T(std::forward<U>(value));
501 }
502
503 template <typename T, size_t inlineCapacity, typename Allocator>
504 template <typename U>
505 inline void Deque<T, inlineCapacity, Allocator>::push_front(U&& value) {
506 expandCapacityIfNeeded();
507 if (!m_start)
508 m_start = m_buffer.capacity() - 1;
509 else
510 --m_start;
511 new (NotNull, &m_buffer.buffer()[m_start]) T(std::forward<U>(value));
512 }
513
514 template <typename T, size_t inlineCapacity, typename Allocator>
515 template <typename... Args>
516 inline void Deque<T, inlineCapacity, Allocator>::emplace_back(Args&&... args) {
517 expandCapacityIfNeeded();
518 T* newElement = &m_buffer.buffer()[m_end];
519 if (m_end == m_buffer.capacity() - 1)
520 m_end = 0;
521 else
522 ++m_end;
523 new (NotNull, newElement) T(std::forward<Args>(args)...);
524 }
525
526 template <typename T, size_t inlineCapacity, typename Allocator>
527 template <typename... Args>
528 inline void Deque<T, inlineCapacity, Allocator>::emplace_front(Args&&... args) {
529 expandCapacityIfNeeded();
530 if (!m_start)
531 m_start = m_buffer.capacity() - 1;
532 else
533 --m_start;
534 new (NotNull, &m_buffer.buffer()[m_start]) T(std::forward<Args>(args)...);
535 }
536
537 template <typename T, size_t inlineCapacity, typename Allocator>
538 inline void Deque<T, inlineCapacity, Allocator>::pop_front() {
539 DCHECK(!isEmpty());
540 TypeOperations::destruct(&m_buffer.buffer()[m_start],
541 &m_buffer.buffer()[m_start + 1]);
542 m_buffer.clearUnusedSlots(&m_buffer.buffer()[m_start],
543 &m_buffer.buffer()[m_start + 1]);
544 if (m_start == m_buffer.capacity() - 1)
545 m_start = 0;
546 else
547 ++m_start;
548 }
549
550 template <typename T, size_t inlineCapacity, typename Allocator>
551 inline void Deque<T, inlineCapacity, Allocator>::pop_back() {
552 DCHECK(!isEmpty());
553 if (!m_end)
554 m_end = m_buffer.capacity() - 1;
555 else
556 --m_end;
557 TypeOperations::destruct(&m_buffer.buffer()[m_end],
558 &m_buffer.buffer()[m_end + 1]);
559 m_buffer.clearUnusedSlots(&m_buffer.buffer()[m_end],
560 &m_buffer.buffer()[m_end + 1]);
561 }
562
563 template <typename T, size_t inlineCapacity, typename Allocator>
564 inline void Deque<T, inlineCapacity, Allocator>::erase(iterator& it) {
565 erase(it.m_index);
566 }
567
568 template <typename T, size_t inlineCapacity, typename Allocator>
569 inline void Deque<T, inlineCapacity, Allocator>::erase(const_iterator& it) {
570 erase(it.m_index);
571 }
572
573 template <typename T, size_t inlineCapacity, typename Allocator>
574 inline void Deque<T, inlineCapacity, Allocator>::erase(size_t position) {
575 if (position == m_end)
576 return;
577
578 T* buffer = m_buffer.buffer();
579 TypeOperations::destruct(&buffer[position], &buffer[position + 1]);
580
581 // Find which segment of the circular buffer contained the remove element,
582 // and only move elements in that part.
583 if (position >= m_start) {
584 TypeOperations::moveOverlapping(buffer + m_start, buffer + position,
585 buffer + m_start + 1);
586 m_buffer.clearUnusedSlots(buffer + m_start, buffer + m_start + 1);
587 m_start = (m_start + 1) % m_buffer.capacity();
588 } else {
589 TypeOperations::moveOverlapping(buffer + position + 1, buffer + m_end,
590 buffer + position);
591 m_buffer.clearUnusedSlots(buffer + m_end - 1, buffer + m_end);
592 m_end = (m_end - 1 + m_buffer.capacity()) % m_buffer.capacity();
593 }
594 }
595
596 template <typename T, size_t inlineCapacity, typename Allocator>
597 inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase()
598 : m_deque(0) {}
599
600 template <typename T, size_t inlineCapacity, typename Allocator>
601 inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase(
602 const Deque<T, inlineCapacity, Allocator>* deque,
603 size_t index)
604 : m_deque(const_cast<Deque<T, inlineCapacity, Allocator>*>(deque)),
605 m_index(index) {}
606
607 template <typename T, size_t inlineCapacity, typename Allocator>
608 inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase(
609 const DequeIteratorBase& other)
610 : m_deque(other.m_deque), m_index(other.m_index) {}
611
612 template <typename T, size_t inlineCapacity, typename Allocator>
613 inline DequeIteratorBase<T, inlineCapacity, Allocator>&
614 DequeIteratorBase<T, inlineCapacity, Allocator>::operator=(
615 const DequeIteratorBase<T, 0, Allocator>& other) {
616 m_deque = other.m_deque;
617 m_index = other.m_index;
618 return *this;
619 }
620
621 template <typename T, size_t inlineCapacity, typename Allocator>
622 inline DequeIteratorBase<T, inlineCapacity, Allocator>::~DequeIteratorBase() {}
623
624 template <typename T, size_t inlineCapacity, typename Allocator>
625 inline bool DequeIteratorBase<T, inlineCapacity, Allocator>::isEqual(
626 const DequeIteratorBase& other) const {
627 return m_index == other.m_index;
628 }
629
630 template <typename T, size_t inlineCapacity, typename Allocator>
631 inline void DequeIteratorBase<T, inlineCapacity, Allocator>::increment() {
632 DCHECK_NE(m_index, m_deque->m_end);
633 DCHECK(m_deque->m_buffer.capacity());
634 if (m_index == m_deque->m_buffer.capacity() - 1)
635 m_index = 0;
636 else
637 ++m_index;
638 }
639
640 template <typename T, size_t inlineCapacity, typename Allocator>
641 inline void DequeIteratorBase<T, inlineCapacity, Allocator>::decrement() {
642 DCHECK_NE(m_index, m_deque->m_start);
643 DCHECK(m_deque->m_buffer.capacity());
644 if (!m_index)
645 m_index = m_deque->m_buffer.capacity() - 1;
646 else
647 --m_index;
648 }
649
650 template <typename T, size_t inlineCapacity, typename Allocator>
651 inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::after() const {
652 RELEASE_ASSERT(m_index != m_deque->m_end);
653 return &m_deque->m_buffer.buffer()[m_index];
654 }
655
656 template <typename T, size_t inlineCapacity, typename Allocator>
657 inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::before() const {
658 RELEASE_ASSERT(m_index != m_deque->m_start);
659 if (!m_index)
660 return &m_deque->m_buffer.buffer()[m_deque->m_buffer.capacity() - 1];
661 return &m_deque->m_buffer.buffer()[m_index - 1];
662 }
663
664 // This is only called if the allocator is a HeapAllocator. It is used when
665 // visiting during a tracing GC.
666 template <typename T, size_t inlineCapacity, typename Allocator>
667 template <typename VisitorDispatcher>
668 void Deque<T, inlineCapacity, Allocator>::trace(VisitorDispatcher visitor) {
669 DCHECK(Allocator::isGarbageCollected) << "Garbage collector must be enabled.";
670 const T* bufferBegin = m_buffer.buffer();
671 const T* end = bufferBegin + m_end;
672 if (IsTraceableInCollectionTrait<VectorTraits<T>>::value) {
673 if (m_start <= m_end) {
674 for (const T* bufferEntry = bufferBegin + m_start; bufferEntry != end;
675 bufferEntry++)
676 Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(
677 visitor, *const_cast<T*>(bufferEntry));
678 } else {
679 for (const T* bufferEntry = bufferBegin; bufferEntry != end;
680 bufferEntry++)
681 Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(
682 visitor, *const_cast<T*>(bufferEntry));
683 const T* bufferEnd = m_buffer.buffer() + m_buffer.capacity();
684 for (const T* bufferEntry = bufferBegin + m_start;
685 bufferEntry != bufferEnd; bufferEntry++)
686 Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(
687 visitor, *const_cast<T*>(bufferEntry));
688 }
689 }
690 if (m_buffer.hasOutOfLineBuffer()) {
691 Allocator::markNoTracing(visitor, m_buffer.buffer());
692 Allocator::registerBackingStoreReference(visitor, m_buffer.bufferSlot());
693 }
694 }
695
696 template <typename T, size_t inlineCapacity, typename Allocator>
697 inline void swap(Deque<T, inlineCapacity, Allocator>& a,
698 Deque<T, inlineCapacity, Allocator>& b) {
699 a.swap(b);
700 }
701
702 } // namespace WTF
703
704 using WTF::Deque;
705
706 #endif // WTF_Deque_h
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/DataLog.cpp ('k') | third_party/WebKit/Source/wtf/DoublyLinkedList.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698