| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart.collection; | 5 part of dart.collection; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A [Queue] is a collection that can be manipulated at both ends. One | 8 * A [Queue] is a collection that can be manipulated at both ends. One |
| 9 * can iterate over the elements of a queue through [forEach] or with | 9 * can iterate over the elements of a queue through [forEach] or with |
| 10 * an [Iterator]. | 10 * an [Iterator]. |
| 11 * | 11 * |
| 12 * It is generally not allowed to modify the queue (add or remove entries) while | 12 * It is generally not allowed to modify the queue (add or remove entries) while |
| 13 * an operation on the queue is being performed, for example during a call to | 13 * an operation on the queue is being performed, for example during a call to |
| 14 * [forEach]. | 14 * [forEach]. |
| 15 * Modifying the queue while it is being iterated will most likely break the | 15 * Modifying the queue while it is being iterated will most likely break the |
| 16 * iteration. | 16 * iteration. |
| 17 * This goes both for using the [iterator] directly, or for iterating an | 17 * This goes both for using the [iterator] directly, or for iterating an |
| 18 * `Iterable` returned by a method like [map] or [where]. | 18 * `Iterable` returned by a method like [map] or [where]. |
| 19 */ | 19 */ |
| 20 abstract class Queue<E> implements EfficientLengthIterable<E> { | 20 abstract class Queue<E> implements EfficientLengthIterable<E> { |
| 21 | |
| 22 /** | 21 /** |
| 23 * Creates a queue. | 22 * Creates a queue. |
| 24 */ | 23 */ |
| 25 factory Queue() = ListQueue<E>; | 24 factory Queue() = ListQueue<E>; |
| 26 | 25 |
| 27 /** | 26 /** |
| 28 * Creates a queue containing all [elements]. | 27 * Creates a queue containing all [elements]. |
| 29 * | 28 * |
| 30 * The element order in the queue is as if the elements were added using | 29 * The element order in the queue is as if the elements were added using |
| 31 * [addLast] in the order provided by [elements.iterator]. | 30 * [addLast] in the order provided by [elements.iterator]. |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 * The `test` function must not throw or modify the queue. | 87 * The `test` function must not throw or modify the queue. |
| 89 */ | 88 */ |
| 90 void retainWhere(bool test(E element)); | 89 void retainWhere(bool test(E element)); |
| 91 | 90 |
| 92 /** | 91 /** |
| 93 * Removes all elements in the queue. The size of the queue becomes zero. | 92 * Removes all elements in the queue. The size of the queue becomes zero. |
| 94 */ | 93 */ |
| 95 void clear(); | 94 void clear(); |
| 96 } | 95 } |
| 97 | 96 |
| 98 | |
| 99 class _DoubleLink<Link extends _DoubleLink> { | 97 class _DoubleLink<Link extends _DoubleLink> { |
| 100 Link _previousLink; | 98 Link _previousLink; |
| 101 Link _nextLink; | 99 Link _nextLink; |
| 102 | 100 |
| 103 void _link(Link previous, Link next) { | 101 void _link(Link previous, Link next) { |
| 104 _nextLink = next; | 102 _nextLink = next; |
| 105 _previousLink = previous; | 103 _previousLink = previous; |
| 106 if (previous != null) previous._nextLink = this; | 104 if (previous != null) previous._nextLink = this; |
| 107 if (next != null) next._previousLink = this; | 105 if (next != null) next._previousLink = this; |
| 108 } | 106 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 } | 146 } |
| 149 | 147 |
| 150 /** | 148 /** |
| 151 * Interface for the link classes used by [DoubleLinkedQueue]. | 149 * Interface for the link classes used by [DoubleLinkedQueue]. |
| 152 * | 150 * |
| 153 * Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel] | 151 * Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel] |
| 154 * implement this interface. | 152 * implement this interface. |
| 155 * The entry contains a link back to the queue, so calling `append` | 153 * The entry contains a link back to the queue, so calling `append` |
| 156 * or `prepend` can correctly update the element count. | 154 * or `prepend` can correctly update the element count. |
| 157 */ | 155 */ |
| 158 abstract class _DoubleLinkedQueueEntry<E> | 156 abstract class _DoubleLinkedQueueEntry<E> extends DoubleLinkedQueueEntry<E> { |
| 159 extends DoubleLinkedQueueEntry<E> { | |
| 160 DoubleLinkedQueue<E> _queue; | 157 DoubleLinkedQueue<E> _queue; |
| 161 _DoubleLinkedQueueEntry(E element, this._queue) : super(element); | 158 _DoubleLinkedQueueEntry(E element, this._queue) : super(element); |
| 162 | 159 |
| 163 DoubleLinkedQueueEntry<E> _asNonSentinelEntry(); | 160 DoubleLinkedQueueEntry<E> _asNonSentinelEntry(); |
| 164 | 161 |
| 165 void _append(E e) { | 162 void _append(E e) { |
| 166 new _DoubleLinkedQueueElement<E>(e, _queue)._link(this, _nextLink); | 163 new _DoubleLinkedQueueElement<E>(e, _queue)._link(this, _nextLink); |
| 167 } | 164 } |
| 168 | 165 |
| 169 void _prepend(E e) { | 166 void _prepend(E e) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 | 222 |
| 226 /** | 223 /** |
| 227 * A sentinel in a double linked list is used to manipulate the list | 224 * A sentinel in a double linked list is used to manipulate the list |
| 228 * at both ends. | 225 * at both ends. |
| 229 * A double linked list has exactly one sentinel, | 226 * A double linked list has exactly one sentinel, |
| 230 * which is the only entry when the list is constructed. | 227 * which is the only entry when the list is constructed. |
| 231 * Initially, a sentinel has its next and previous entry point to itself. | 228 * Initially, a sentinel has its next and previous entry point to itself. |
| 232 * A sentinel does not box any user element. | 229 * A sentinel does not box any user element. |
| 233 */ | 230 */ |
| 234 class _DoubleLinkedQueueSentinel<E> extends _DoubleLinkedQueueEntry<E> { | 231 class _DoubleLinkedQueueSentinel<E> extends _DoubleLinkedQueueEntry<E> { |
| 235 _DoubleLinkedQueueSentinel(DoubleLinkedQueue<E> queue) | 232 _DoubleLinkedQueueSentinel(DoubleLinkedQueue<E> queue) : super(null, queue) { |
| 236 : super(null, queue) { | |
| 237 _previousLink = this; | 233 _previousLink = this; |
| 238 _nextLink = this; | 234 _nextLink = this; |
| 239 } | 235 } |
| 240 | 236 |
| 241 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { | 237 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { |
| 242 return null; | 238 return null; |
| 243 } | 239 } |
| 244 | 240 |
| 245 /** Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty. */ | 241 /** Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty. */ |
| 246 E _remove() { | 242 E _remove() { |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 } | 334 } |
| 339 | 335 |
| 340 void _filter(bool test(E element), bool removeMatching) { | 336 void _filter(bool test(E element), bool removeMatching) { |
| 341 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; | 337 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
| 342 while (!identical(entry, _sentinel)) { | 338 while (!identical(entry, _sentinel)) { |
| 343 bool matches = test(entry._element); | 339 bool matches = test(entry._element); |
| 344 if (!identical(this, entry._queue)) { | 340 if (!identical(this, entry._queue)) { |
| 345 // Entry must still be in the queue. | 341 // Entry must still be in the queue. |
| 346 throw new ConcurrentModificationError(this); | 342 throw new ConcurrentModificationError(this); |
| 347 } | 343 } |
| 348 _DoubleLinkedQueueEntry<E> next = entry._nextLink; // Cannot be null. | 344 _DoubleLinkedQueueEntry<E> next = entry._nextLink; // Cannot be null. |
| 349 if (identical(removeMatching, matches)) { | 345 if (identical(removeMatching, matches)) { |
| 350 entry._remove(); | 346 entry._remove(); |
| 351 _elementCount--; | 347 _elementCount--; |
| 352 } | 348 } |
| 353 entry = next; | 349 entry = next; |
| 354 } | 350 } |
| 355 } | 351 } |
| 356 | 352 |
| 357 void removeWhere(bool test(E element)) { | 353 void removeWhere(bool test(E element)) { |
| 358 _filter(test, true); | 354 _filter(test, true); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 int _head; | 503 int _head; |
| 508 int _tail; | 504 int _tail; |
| 509 int _modificationCount = 0; | 505 int _modificationCount = 0; |
| 510 | 506 |
| 511 /** | 507 /** |
| 512 * Create an empty queue. | 508 * Create an empty queue. |
| 513 * | 509 * |
| 514 * If [initialCapacity] is given, prepare the queue for at least that many | 510 * If [initialCapacity] is given, prepare the queue for at least that many |
| 515 * elements. | 511 * elements. |
| 516 */ | 512 */ |
| 517 ListQueue([int initialCapacity]) : _head = 0, _tail = 0 { | 513 ListQueue([int initialCapacity]) |
| 514 : _head = 0, |
| 515 _tail = 0 { |
| 518 if (initialCapacity == null || initialCapacity < _INITIAL_CAPACITY) { | 516 if (initialCapacity == null || initialCapacity < _INITIAL_CAPACITY) { |
| 519 initialCapacity = _INITIAL_CAPACITY; | 517 initialCapacity = _INITIAL_CAPACITY; |
| 520 } else if (!_isPowerOf2(initialCapacity)) { | 518 } else if (!_isPowerOf2(initialCapacity)) { |
| 521 initialCapacity = _nextPowerOf2(initialCapacity); | 519 initialCapacity = _nextPowerOf2(initialCapacity); |
| 522 } | 520 } |
| 523 assert(_isPowerOf2(initialCapacity)); | 521 assert(_isPowerOf2(initialCapacity)); |
| 524 _table = new List<E>(initialCapacity); | 522 _table = new List<E>(initialCapacity); |
| 525 } | 523 } |
| 526 | 524 |
| 527 /** | 525 /** |
| (...skipping 24 matching lines...) Expand all Loading... |
| 552 result.addLast(element as Object/*=E*/); | 550 result.addLast(element as Object/*=E*/); |
| 553 } | 551 } |
| 554 return result; | 552 return result; |
| 555 } | 553 } |
| 556 } | 554 } |
| 557 | 555 |
| 558 // Iterable interface. | 556 // Iterable interface. |
| 559 | 557 |
| 560 Iterator<E> get iterator => new _ListQueueIterator<E>(this); | 558 Iterator<E> get iterator => new _ListQueueIterator<E>(this); |
| 561 | 559 |
| 562 void forEach(void action (E element)) { | 560 void forEach(void action(E element)) { |
| 563 int modificationCount = _modificationCount; | 561 int modificationCount = _modificationCount; |
| 564 for (int i = _head; i != _tail; i = (i + 1) & (_table.length - 1)) { | 562 for (int i = _head; i != _tail; i = (i + 1) & (_table.length - 1)) { |
| 565 action(_table[i]); | 563 action(_table[i]); |
| 566 _checkModification(modificationCount); | 564 _checkModification(modificationCount); |
| 567 } | 565 } |
| 568 } | 566 } |
| 569 | 567 |
| 570 bool get isEmpty => _head == _tail; | 568 bool get isEmpty => _head == _tail; |
| 571 | 569 |
| 572 int get length => (_tail - _head) & (_table.length - 1); | 570 int get length => (_tail - _head) & (_table.length - 1); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 585 if (_head == _tail) throw IterableElementError.noElement(); | 583 if (_head == _tail) throw IterableElementError.noElement(); |
| 586 if (length > 1) throw IterableElementError.tooMany(); | 584 if (length > 1) throw IterableElementError.tooMany(); |
| 587 return _table[_head]; | 585 return _table[_head]; |
| 588 } | 586 } |
| 589 | 587 |
| 590 E elementAt(int index) { | 588 E elementAt(int index) { |
| 591 RangeError.checkValidIndex(index, this); | 589 RangeError.checkValidIndex(index, this); |
| 592 return _table[(_head + index) & (_table.length - 1)]; | 590 return _table[(_head + index) & (_table.length - 1)]; |
| 593 } | 591 } |
| 594 | 592 |
| 595 List<E> toList({ bool growable: true }) { | 593 List<E> toList({bool growable: true}) { |
| 596 List<E> list; | 594 List<E> list; |
| 597 if (growable) { | 595 if (growable) { |
| 598 list = new List<E>()..length = length; | 596 list = new List<E>()..length = length; |
| 599 } else { | 597 } else { |
| 600 list = new List<E>(length); | 598 list = new List<E>(length); |
| 601 } | 599 } |
| 602 _writeToList(list); | 600 _writeToList(list); |
| 603 return list; | 601 return list; |
| 604 } | 602 } |
| 605 | 603 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 } | 691 } |
| 694 _head = _tail = 0; | 692 _head = _tail = 0; |
| 695 _modificationCount++; | 693 _modificationCount++; |
| 696 } | 694 } |
| 697 } | 695 } |
| 698 | 696 |
| 699 String toString() => IterableBase.iterableToFullString(this, "{", "}"); | 697 String toString() => IterableBase.iterableToFullString(this, "{", "}"); |
| 700 | 698 |
| 701 // Queue interface. | 699 // Queue interface. |
| 702 | 700 |
| 703 void addLast(E value) { _add(value); } | 701 void addLast(E value) { |
| 702 _add(value); |
| 703 } |
| 704 | 704 |
| 705 void addFirst(E value) { | 705 void addFirst(E value) { |
| 706 _head = (_head - 1) & (_table.length - 1); | 706 _head = (_head - 1) & (_table.length - 1); |
| 707 _table[_head] = value; | 707 _table[_head] = value; |
| 708 if (_head == _tail) _grow(); | 708 if (_head == _tail) _grow(); |
| 709 _modificationCount++; | 709 _modificationCount++; |
| 710 } | 710 } |
| 711 | 711 |
| 712 E removeFirst() { | 712 E removeFirst() { |
| 713 if (_head == _tail) throw IterableElementError.noElement(); | 713 if (_head == _tail) throw IterableElementError.noElement(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 739 /** | 739 /** |
| 740 * Rounds [number] up to the nearest power of 2. | 740 * Rounds [number] up to the nearest power of 2. |
| 741 * | 741 * |
| 742 * If [number] is a power of 2 already, it is returned. | 742 * If [number] is a power of 2 already, it is returned. |
| 743 * | 743 * |
| 744 * Only works for positive numbers. | 744 * Only works for positive numbers. |
| 745 */ | 745 */ |
| 746 static int _nextPowerOf2(int number) { | 746 static int _nextPowerOf2(int number) { |
| 747 assert(number > 0); | 747 assert(number > 0); |
| 748 number = (number << 1) - 1; | 748 number = (number << 1) - 1; |
| 749 for(;;) { | 749 for (;;) { |
| 750 int nextNumber = number & (number - 1); | 750 int nextNumber = number & (number - 1); |
| 751 if (nextNumber == 0) return number; | 751 if (nextNumber == 0) return number; |
| 752 number = nextNumber; | 752 number = nextNumber; |
| 753 } | 753 } |
| 754 } | 754 } |
| 755 | 755 |
| 756 /** Check if the queue has been modified during iteration. */ | 756 /** Check if the queue has been modified during iteration. */ |
| 757 void _checkModification(int expectedModificationCount) { | 757 void _checkModification(int expectedModificationCount) { |
| 758 if (expectedModificationCount != _modificationCount) { | 758 if (expectedModificationCount != _modificationCount) { |
| 759 throw new ConcurrentModificationError(this); | 759 throw new ConcurrentModificationError(this); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 872 _queue._checkModification(_modificationCount); | 872 _queue._checkModification(_modificationCount); |
| 873 if (_position == _end) { | 873 if (_position == _end) { |
| 874 _current = null; | 874 _current = null; |
| 875 return false; | 875 return false; |
| 876 } | 876 } |
| 877 _current = _queue._table[_position]; | 877 _current = _queue._table[_position]; |
| 878 _position = (_position + 1) & (_queue._table.length - 1); | 878 _position = (_position + 1) & (_queue._table.length - 1); |
| 879 return true; | 879 return true; |
| 880 } | 880 } |
| 881 } | 881 } |
| OLD | NEW |