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]. |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
315 E removeFirst() { | 315 E removeFirst() { |
316 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; | 316 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; |
317 E result = firstEntry._remove(); | 317 E result = firstEntry._remove(); |
318 _elementCount--; | 318 _elementCount--; |
319 return result; | 319 return result; |
320 } | 320 } |
321 | 321 |
322 bool remove(Object o) { | 322 bool remove(Object o) { |
323 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; | 323 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
324 while (!identical(entry, _sentinel)) { | 324 while (!identical(entry, _sentinel)) { |
325 if (entry._element == o) { | 325 bool equals = (entry._element == o); |
326 if (!identical(this, entry._queue)) { | |
327 // Entry must still be in the queue. | |
328 throw new ConcurrentModificationError(this); | |
329 } | |
330 if (equals) { | |
326 entry._remove(); | 331 entry._remove(); |
327 _elementCount--; | 332 _elementCount--; |
328 return true; | 333 return true; |
329 } | 334 } |
330 entry = entry._nextLink; | 335 entry = entry._nextLink; |
331 } | 336 } |
332 return false; | 337 return false; |
333 } | 338 } |
334 | 339 |
335 void _filter(bool test(E element), bool removeMatching) { | 340 void _filter(bool test(E element), bool removeMatching) { |
336 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; | 341 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
337 while (!identical(entry, _sentinel)) { | 342 while (!identical(entry, _sentinel)) { |
338 _DoubleLinkedQueueEntry<E> next = entry._nextLink; | 343 bool matches = test(entry._element); |
339 if (identical(removeMatching, test(entry._element))) { | 344 if (!identical(this, entry._queue)) { |
345 // Entry must still be in the queue. | |
346 throw new ConcurrentModificationError(this); | |
347 } | |
348 _DoubleLinkedQueueEntry<E> next = entry._nextLink; // Cannot be null. | |
349 if (identical(removeMatching, matches)) { | |
340 entry._remove(); | 350 entry._remove(); |
341 _elementCount--; | 351 _elementCount--; |
342 } | 352 } |
343 entry = next; | 353 entry = next; |
344 } | 354 } |
345 } | 355 } |
346 | 356 |
347 void removeWhere(bool test(E element)) { | 357 void removeWhere(bool test(E element)) { |
348 _filter(test, true); | 358 _filter(test, true); |
349 } | 359 } |
350 | 360 |
351 void retainWhere(bool test(E element)) { | 361 void retainWhere(bool test(E element)) { |
352 _filter(test, false); | 362 _filter(test, false); |
353 } | 363 } |
354 | 364 |
355 E get first { | 365 E get first { |
356 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; | 366 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; |
357 return firstEntry._element; | 367 return firstEntry._element; |
358 } | 368 } |
359 | 369 |
360 E get last { | 370 E get last { |
361 _DoubleLinkedQueueEntry<E> lastEntry = _sentinel._previousLink; | 371 _DoubleLinkedQueueEntry<E> lastEntry = _sentinel._previousLink; |
362 return lastEntry._element; | 372 return lastEntry._element; |
363 } | 373 } |
364 | 374 |
365 E get single { | 375 E get single { |
366 // Note that this throws correctly if the queue is empty | 376 // Note that this throws correctly if the queue is empty |
367 // because reading element on the sentinel throws. | 377 // because reading the element of the sentinel throws. |
368 if (identical(_sentinel._nextLink, _sentinel._previousLink)) { | 378 if (identical(_sentinel._nextLink, _sentinel._previousLink)) { |
369 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; | 379 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
370 return entry._element; | 380 return entry._element; |
371 } | 381 } |
372 throw IterableElementError.tooMany(); | 382 throw IterableElementError.tooMany(); |
373 } | 383 } |
374 | 384 |
385 /** | |
386 * The entry object of the first element in the queue. | |
387 * | |
388 * Each element of the queue has an associated [DoubleLinkedQueueEntry]. | |
389 * Returns the entry object corresponding to the first element of the queue. | |
390 * | |
391 * The entry objects can also be accessed using [lastEntry], | |
392 * and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and | |
393 * [DoubleLinkedQueueEntry.previousEntry()]. | |
394 */ | |
395 DoubleLinkedQueueEntry<E> firstEntry() { | |
396 return _sentinel.nextEntry(); | |
397 } | |
398 | |
399 /** | |
400 * The entry object of the last element in the queue. | |
401 * | |
402 * Each element of the queue has an associated [DoubleLinkedQueueEntry]. | |
403 * Returns the entry object corresponding to the last element of the queue. | |
404 * | |
405 * The entry objects can also be accessed using [firstEntry], | |
406 * and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and | |
407 * [DoubleLinkedQueueEntry.previousEntry()]. | |
408 */ | |
375 DoubleLinkedQueueEntry<E> lastEntry() { | 409 DoubleLinkedQueueEntry<E> lastEntry() { |
floitsch
2016/12/01 18:31:09
not a getter?
argh :(
| |
376 return _sentinel.previousEntry(); | 410 return _sentinel.previousEntry(); |
377 } | 411 } |
378 | 412 |
379 DoubleLinkedQueueEntry<E> firstEntry() { | |
380 return _sentinel.nextEntry(); | |
381 } | |
382 | |
383 bool get isEmpty { | 413 bool get isEmpty { |
384 return (identical(_sentinel._nextLink, _sentinel)); | 414 return (identical(_sentinel._nextLink, _sentinel)); |
385 } | 415 } |
386 | 416 |
387 void clear() { | 417 void clear() { |
388 _sentinel._nextLink = _sentinel; | 418 _sentinel._nextLink = _sentinel; |
389 _sentinel._previousLink = _sentinel; | 419 _sentinel._previousLink = _sentinel; |
390 _elementCount = 0; | 420 _elementCount = 0; |
391 } | 421 } |
392 | 422 |
393 void forEachEntry(void f(DoubleLinkedQueueEntry<E> element)) { | 423 /** |
424 * Calls [action] for each entry object of this double-linked queue. | |
425 * | |
426 * Each element of the queue has an associated [DoubleLinkedQueueEntry]. | |
427 * This method iterates the entry objects from first to last and calls | |
428 * [action] with each object in turn. | |
429 * | |
430 * The entry objects can also be accessed using [firstEntry] and [lastEntry], | |
431 * and iterated using [DoubleLinkedQueueEntry.nextEntry()] and | |
432 * [DoubleLinkedQueueEntry.previousEntry()]. | |
433 * | |
434 * The [action] function can use methods on [DoubleLinkedQueueEntry] to remove | |
435 * the entry or it can insert elements before or after then entry. | |
436 * If the current entry is removed, iteration continues with the entry that | |
437 * was following the current entry when [action] was called. Any elements | |
438 * inserted after the current element before it is removed will not be | |
439 * visited by the iteration. | |
440 */ | |
441 void forEachEntry(void action(DoubleLinkedQueueEntry<E> element)) { | |
394 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; | 442 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
395 while (!identical(entry, _sentinel)) { | 443 while (!identical(entry, _sentinel)) { |
396 _DoubleLinkedQueueEntry<E> nextEntry = entry._nextLink; | |
397 _DoubleLinkedQueueElement<E> element = entry; | 444 _DoubleLinkedQueueElement<E> element = entry; |
398 f(element); | 445 _DoubleLinkedQueueEntry<E> next = element._nextLink; |
399 entry = nextEntry; | 446 // Remember both entry and entry._nextLink. |
447 // If someone calls `element.remove()` we continue from `next`. | |
448 // Otherwise we use the value of entry._nextLink which may have been | |
449 // updated. | |
450 action(element); | |
451 if (identical(this, entry._queue)) { | |
452 next = entry._nextLink; | |
453 } else if (!identical(this, next._queue)) { | |
454 throw new ConcurrentModificationError(this); | |
455 } | |
456 entry = next; | |
400 } | 457 } |
401 } | 458 } |
402 | 459 |
403 _DoubleLinkedQueueIterator<E> get iterator { | 460 _DoubleLinkedQueueIterator<E> get iterator { |
404 return new _DoubleLinkedQueueIterator<E>(_sentinel); | 461 return new _DoubleLinkedQueueIterator<E>(_sentinel); |
405 } | 462 } |
406 | 463 |
407 String toString() => IterableBase.iterableToFullString(this, '{', '}'); | 464 String toString() => IterableBase.iterableToFullString(this, '{', '}'); |
408 } | 465 } |
409 | 466 |
410 class _DoubleLinkedQueueIterator<E> implements Iterator<E> { | 467 class _DoubleLinkedQueueIterator<E> implements Iterator<E> { |
411 _DoubleLinkedQueueSentinel<E> _sentinel; | 468 _DoubleLinkedQueueSentinel<E> _sentinel; |
412 _DoubleLinkedQueueEntry<E> _nextEntry = null; | 469 _DoubleLinkedQueueEntry<E> _nextEntry = null; |
413 E _current; | 470 E _current; |
414 | 471 |
415 _DoubleLinkedQueueIterator(_DoubleLinkedQueueSentinel<E> sentinel) | 472 _DoubleLinkedQueueIterator(_DoubleLinkedQueueSentinel<E> sentinel) |
416 : _sentinel = sentinel, | 473 : _sentinel = sentinel, |
417 _nextEntry = sentinel._nextLink; | 474 _nextEntry = sentinel._nextLink; |
418 | 475 |
419 bool moveNext() { | 476 bool moveNext() { |
420 if (identical(_nextEntry, _sentinel)) { | 477 if (identical(_nextEntry, _sentinel)) { |
421 _current = null; | 478 _current = null; |
422 _nextEntry = null; | 479 _nextEntry = null; |
423 _sentinel = null; | 480 _sentinel = null; |
424 return false; | 481 return false; |
425 } | 482 } |
426 _DoubleLinkedQueueElement<E> elementEntry = _nextEntry; | 483 _DoubleLinkedQueueElement<E> elementEntry = _nextEntry; |
427 if (elementEntry._queue == null) { | 484 if (!identical(_sentinel._queue, elementEntry._queue)) { |
428 throw new ConcurrentModificationError(_sentinel._queue); | 485 throw new ConcurrentModificationError(_sentinel._queue); |
429 } | 486 } |
430 _current = elementEntry._element; | 487 _current = elementEntry._element; |
431 _nextEntry = elementEntry._nextLink; | 488 _nextEntry = elementEntry._nextLink; |
432 return true; | 489 return true; |
433 } | 490 } |
434 | 491 |
435 E get current => _current; | 492 E get current => _current; |
436 } | 493 } |
437 | 494 |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
707 void _add(E element) { | 764 void _add(E element) { |
708 _table[_tail] = element; | 765 _table[_tail] = element; |
709 _tail = (_tail + 1) & (_table.length - 1); | 766 _tail = (_tail + 1) & (_table.length - 1); |
710 if (_head == _tail) _grow(); | 767 if (_head == _tail) _grow(); |
711 _modificationCount++; | 768 _modificationCount++; |
712 } | 769 } |
713 | 770 |
714 /** | 771 /** |
715 * Removes the element at [offset] into [_table]. | 772 * Removes the element at [offset] into [_table]. |
716 * | 773 * |
717 * Removal is performed by linerarly moving elements either before or after | 774 * Removal is performed by linearly moving elements either before or after |
718 * [offset] by one position. | 775 * [offset] by one position. |
719 * | 776 * |
720 * Returns the new offset of the following element. This may be the same | 777 * Returns the new offset of the following element. This may be the same |
721 * offset or the following offset depending on how elements are moved | 778 * offset or the following offset depending on how elements are moved |
722 * to fill the hole. | 779 * to fill the hole. |
723 */ | 780 */ |
724 int _remove(int offset) { | 781 int _remove(int offset) { |
725 int mask = _table.length - 1; | 782 int mask = _table.length - 1; |
726 int startDistance = (offset - _head) & mask; | 783 int startDistance = (offset - _head) & mask; |
727 int endDistance = (_tail - offset) & mask; | 784 int endDistance = (_tail - offset) & mask; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
815 _queue._checkModification(_modificationCount); | 872 _queue._checkModification(_modificationCount); |
816 if (_position == _end) { | 873 if (_position == _end) { |
817 _current = null; | 874 _current = null; |
818 return false; | 875 return false; |
819 } | 876 } |
820 _current = _queue._table[_position]; | 877 _current = _queue._table[_position]; |
821 _position = (_position + 1) & (_queue._table.length - 1); | 878 _position = (_position + 1) & (_queue._table.length - 1); |
822 return true; | 879 return true; |
823 } | 880 } |
824 } | 881 } |
OLD | NEW |