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

Side by Side Diff: sdk/lib/collection/queue.dart

Issue 1973903005: Make DoubleLinkedQueueEntry subclassable again. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 7 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 */ 89 */
90 void retainWhere(bool test(E element)); 90 void retainWhere(bool test(E element));
91 91
92 /** 92 /**
93 * Removes all elements in the queue. The size of the queue becomes zero. 93 * Removes all elements in the queue. The size of the queue becomes zero.
94 */ 94 */
95 void clear(); 95 void clear();
96 } 96 }
97 97
98 98
99 class _DoubleLink<E extends _DoubleLink> { 99 class _DoubleLink<Link extends _DoubleLink> {
100 E _previousLink; 100 Link _previousLink;
101 E _nextLink; 101 Link _nextLink;
102 102
103 void _link(E previous, E next) { 103 void _link(Link previous, Link next) {
104 _nextLink = next; 104 _nextLink = next;
105 _previousLink = previous; 105 _previousLink = previous;
106 if (previous != null) previous._nextLink = this; 106 if (previous != null) previous._nextLink = this;
107 if (next != null) next._previousLink = this; 107 if (next != null) next._previousLink = this;
108 } 108 }
109 109
110 void _unlink() { 110 void _unlink() {
111 if (_previousLink != null) _previousLink._nextLink = _nextLink; 111 if (_previousLink != null) _previousLink._nextLink = _nextLink;
112 if (_nextLink != null) _nextLink._previousLink = _previousLink; 112 if (_nextLink != null) _nextLink._previousLink = _previousLink;
113 _nextLink = null; 113 _nextLink = null;
114 _previousLink = null; 114 _previousLink = null;
115 } 115 }
116 } 116 }
117 117
118 /** 118 /**
119 * An entry in a doubly linked list. It contains a pointer to the next 119 * An entry in a doubly linked list. It contains a pointer to the next
120 * entry, the previous entry, and the boxed element. 120 * entry, the previous entry, and the boxed element.
121 */ 121 */
122 abstract class DoubleLinkedQueueEntry<E> { 122 class DoubleLinkedQueueEntry<E> extends _DoubleLink<DoubleLinkedQueueEntry<E>> {
123 factory DoubleLinkedQueueEntry(E element) = _UserDoubleLinkedQueueEntry<E>; 123 /// The element in the queue.
124 E element;
124 125
125 /// The element in the queue. 126 DoubleLinkedQueueEntry(this.element);
126 E get element;
127 127
128 /// Appends the given [e] as entry just after this entry. 128 /// Appends the given [e] as entry just after this entry.
129 void append(E e); 129 void append(E e) {
130 new DoubleLinkedQueueEntry<E>(e)._link(this, _nextLink);
131 }
130 132
131 /// Prepends the given [e] as entry just before this entry. 133 /// Prepends the given [e] as entry just before this entry.
132 void prepend(E e);
133
134 /// Returns the previous entry or `null` if there is none.
135 DoubleLinkedQueueEntry<E> previousEntry();
136
137 /// Returns the next entry or `null` if there is none.
138 DoubleLinkedQueueEntry<E> nextEntry();
139 }
140
141 /// Default implementation of a doubly linked queue entry.
142 ///
143 /// This implementation is only used if a user instantiates a
144 /// [DoubleLinkedQueueEntry] directly. The internal implementations don't use
145 /// this class.
146 class _UserDoubleLinkedQueueEntry<E>
147 extends _DoubleLink<_UserDoubleLinkedQueueEntry<E>>
148 implements DoubleLinkedQueueEntry<E> {
149 E element;
150
151 _UserDoubleLinkedQueueEntry(this.element);
152
153 void append(E e) {
154 new _UserDoubleLinkedQueueEntry<E>(e)._link(this, _nextLink);
155 }
156
157 void prepend(E e) { 134 void prepend(E e) {
158 new _UserDoubleLinkedQueueEntry<E>(e)._link(_previousLink, this); 135 new DoubleLinkedQueueEntry<E>(e)._link(_previousLink, this);
159 } 136 }
160 137
161 E remove() { 138 E remove() {
162 _unlink(); 139 _unlink();
163 return element; 140 return element;
164 } 141 }
165 142
143 /// Returns the previous entry or `null` if there is none.
166 DoubleLinkedQueueEntry<E> previousEntry() => _previousLink; 144 DoubleLinkedQueueEntry<E> previousEntry() => _previousLink;
167 145
146 /// Returns the next entry or `null` if there is none.
168 DoubleLinkedQueueEntry<E> nextEntry() => _nextLink; 147 DoubleLinkedQueueEntry<E> nextEntry() => _nextLink;
169 } 148 }
170 149
171 /** 150 /**
172 * Interface for the link classes used by [DoubleLinkedQueue]. 151 * Interface for the link classes used by [DoubleLinkedQueue].
173 * 152 *
174 * Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel] 153 * Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel]
175 * implement this interface. 154 * implement this interface.
176 * The entry contains a link back to the queue, so calling `append` 155 * The entry contains a link back to the queue, so calling `append`
177 * or `prepend` can correctly update the element count. 156 * or `prepend` can correctly update the element count.
178 */ 157 */
179 abstract class _DoubleLinkedQueueEntry<E> 158 abstract class _DoubleLinkedQueueEntry<E>
180 extends _DoubleLink<_DoubleLinkedQueueEntry<E>> { 159 extends DoubleLinkedQueueEntry<E> {
181 DoubleLinkedQueue<E> _queue; 160 DoubleLinkedQueue<E> _queue;
182 _DoubleLinkedQueueEntry(this._queue); 161 _DoubleLinkedQueueEntry(E element, this._queue) : super(element);
183 162
184 DoubleLinkedQueueEntry<E> _asNonSentinelEntry(); 163 DoubleLinkedQueueEntry<E> _asNonSentinelEntry();
185 164
186 void _append(E e) { 165 void _append(E e) {
187 new _DoubleLinkedQueueElement<E>(e, _queue)._link(this, _nextLink); 166 new _DoubleLinkedQueueElement<E>(e, _queue)._link(this, _nextLink);
188 } 167 }
189 168
190 void _prepend(E e) { 169 void _prepend(E e) {
191 new _DoubleLinkedQueueElement<E>(e, _queue)._link(_previousLink, this); 170 new _DoubleLinkedQueueElement<E>(e, _queue)._link(_previousLink, this);
192 } 171 }
193 172
194 E _remove(); 173 E _remove();
195 174
196 E get element; 175 E get _element => element;
197 176
198 DoubleLinkedQueueEntry<E> nextEntry() { 177 DoubleLinkedQueueEntry<E> nextEntry() {
199 return _nextLink._asNonSentinelEntry(); 178 _DoubleLinkedQueueEntry<E> entry =
179 _nextLink as dynamic/*=DoubleLinkedQueueEntry<E>*/;
180 return entry._asNonSentinelEntry();
200 } 181 }
201 182
202 DoubleLinkedQueueEntry<E> previousEntry() { 183 DoubleLinkedQueueEntry<E> previousEntry() {
203 return _previousLink._asNonSentinelEntry(); 184 _DoubleLinkedQueueEntry<E> entry =
185 _previousLink as dynamic/*=DoubleLinkedQueueEntry<E>*/;
186 return entry._asNonSentinelEntry();
204 } 187 }
205 } 188 }
206 189
207 /** 190 /**
208 * The actual entry type used by the [DoubleLinkedQueue]. 191 * The actual entry type used by the [DoubleLinkedQueue].
209 * 192 *
210 * The entry contains a reference to the queue, allowing 193 * The entry contains a reference to the queue, allowing
211 * [append]/[prepend] to update the list length. 194 * [append]/[prepend] to update the list length.
212 */ 195 */
213 class _DoubleLinkedQueueElement<E> extends _DoubleLinkedQueueEntry<E> 196 class _DoubleLinkedQueueElement<E> extends _DoubleLinkedQueueEntry<E> {
214 implements DoubleLinkedQueueEntry<E> { 197 _DoubleLinkedQueueElement(E element, DoubleLinkedQueue<E> queue)
215 E element; 198 : super(element, queue);
216 _DoubleLinkedQueueElement(this.element, DoubleLinkedQueue<E> queue)
217 : super(queue);
218 199
219 void append(E e) { 200 void append(E e) {
220 _append(e); 201 _append(e);
221 if (_queue != null) _queue._elementCount++; 202 if (_queue != null) _queue._elementCount++;
222 } 203 }
223 204
224 void prepend(E e) { 205 void prepend(E e) {
225 _prepend(e); 206 _prepend(e);
226 if (_queue != null) _queue._elementCount++; 207 if (_queue != null) _queue._elementCount++;
227 } 208 }
(...skipping 16 matching lines...) Expand all
244 225
245 /** 226 /**
246 * A sentinel in a double linked list is used to manipulate the list 227 * A sentinel in a double linked list is used to manipulate the list
247 * at both ends. 228 * at both ends.
248 * A double linked list has exactly one sentinel, 229 * A double linked list has exactly one sentinel,
249 * which is the only entry when the list is constructed. 230 * which is the only entry when the list is constructed.
250 * Initially, a sentinel has its next and previous entry point to itself. 231 * Initially, a sentinel has its next and previous entry point to itself.
251 * A sentinel does not box any user element. 232 * A sentinel does not box any user element.
252 */ 233 */
253 class _DoubleLinkedQueueSentinel<E> extends _DoubleLinkedQueueEntry<E> { 234 class _DoubleLinkedQueueSentinel<E> extends _DoubleLinkedQueueEntry<E> {
254 _DoubleLinkedQueueSentinel(DoubleLinkedQueue<E> queue) : super(queue) { 235 _DoubleLinkedQueueSentinel(DoubleLinkedQueue<E> queue)
236 : super(null, queue) {
255 _previousLink = this; 237 _previousLink = this;
256 _nextLink = this; 238 _nextLink = this;
257 } 239 }
258 240
259 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { 241 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() {
260 return null; 242 return null;
261 } 243 }
262 244
263 /** Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty. */ 245 /** Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty. */
264 E _remove() { 246 E _remove() {
265 throw IterableElementError.noElement(); 247 throw IterableElementError.noElement();
266 } 248 }
267 249
268 /** Hit by, e.g., [DoubleLinkedQueue.first] if the queue is empty. */ 250 /** Hit by, e.g., [DoubleLinkedQueue.first] if the queue is empty. */
269 E get element { 251 E get _element {
270 throw IterableElementError.noElement(); 252 throw IterableElementError.noElement();
271 } 253 }
272 } 254 }
273 255
274 /** 256 /**
275 * A [Queue] implementation based on a double-linked list. 257 * A [Queue] implementation based on a double-linked list.
276 * 258 *
277 * Allows constant time add, remove-at-ends and peek operations. 259 * Allows constant time add, remove-at-ends and peek operations.
278 */ 260 */
279 class DoubleLinkedQueue<E> extends Iterable<E> implements Queue<E> { 261 class DoubleLinkedQueue<E> extends Iterable<E> implements Queue<E> {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 E removeFirst() { 315 E removeFirst() {
334 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; 316 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink;
335 E result = firstEntry._remove(); 317 E result = firstEntry._remove();
336 _elementCount--; 318 _elementCount--;
337 return result; 319 return result;
338 } 320 }
339 321
340 bool remove(Object o) { 322 bool remove(Object o) {
341 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; 323 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink;
342 while (!identical(entry, _sentinel)) { 324 while (!identical(entry, _sentinel)) {
343 if (entry.element == o) { 325 if (entry._element == o) {
344 entry._remove(); 326 entry._remove();
345 _elementCount--; 327 _elementCount--;
346 return true; 328 return true;
347 } 329 }
348 entry = entry._nextLink; 330 entry = entry._nextLink;
349 } 331 }
350 return false; 332 return false;
351 } 333 }
352 334
353 void _filter(bool test(E element), bool removeMatching) { 335 void _filter(bool test(E element), bool removeMatching) {
354 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; 336 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink;
355 while (!identical(entry, _sentinel)) { 337 while (!identical(entry, _sentinel)) {
356 _DoubleLinkedQueueEntry<E> next = entry._nextLink; 338 _DoubleLinkedQueueEntry<E> next = entry._nextLink;
357 if (identical(removeMatching, test(entry.element))) { 339 if (identical(removeMatching, test(entry._element))) {
358 entry._remove(); 340 entry._remove();
359 _elementCount--; 341 _elementCount--;
360 } 342 }
361 entry = next; 343 entry = next;
362 } 344 }
363 } 345 }
364 346
365 void removeWhere(bool test(E element)) { 347 void removeWhere(bool test(E element)) {
366 _filter(test, true); 348 _filter(test, true);
367 } 349 }
368 350
369 void retainWhere(bool test(E element)) { 351 void retainWhere(bool test(E element)) {
370 _filter(test, false); 352 _filter(test, false);
371 } 353 }
372 354
373 E get first { 355 E get first {
374 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; 356 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink;
375 return firstEntry.element; 357 return firstEntry._element;
376 } 358 }
377 359
378 E get last { 360 E get last {
379 _DoubleLinkedQueueEntry<E> lastEntry = _sentinel._previousLink; 361 _DoubleLinkedQueueEntry<E> lastEntry = _sentinel._previousLink;
380 return lastEntry.element; 362 return lastEntry._element;
381 } 363 }
382 364
383 E get single { 365 E get single {
384 // Note that this throws correctly if the queue is empty 366 // Note that this throws correctly if the queue is empty
385 // because reading element on the sentinel throws. 367 // because reading element on the sentinel throws.
386 if (identical(_sentinel._nextLink, _sentinel._previousLink)) { 368 if (identical(_sentinel._nextLink, _sentinel._previousLink)) {
387 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; 369 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink;
388 return entry.element; 370 return entry._element;
389 } 371 }
390 throw IterableElementError.tooMany(); 372 throw IterableElementError.tooMany();
391 } 373 }
392 374
393 DoubleLinkedQueueEntry<E> lastEntry() { 375 DoubleLinkedQueueEntry<E> lastEntry() {
394 return _sentinel.previousEntry(); 376 return _sentinel.previousEntry();
395 } 377 }
396 378
397 DoubleLinkedQueueEntry<E> firstEntry() { 379 DoubleLinkedQueueEntry<E> firstEntry() {
398 return _sentinel.nextEntry(); 380 return _sentinel.nextEntry();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 if (identical(_nextEntry, _sentinel)) { 420 if (identical(_nextEntry, _sentinel)) {
439 _current = null; 421 _current = null;
440 _nextEntry = null; 422 _nextEntry = null;
441 _sentinel = null; 423 _sentinel = null;
442 return false; 424 return false;
443 } 425 }
444 _DoubleLinkedQueueElement<E> elementEntry = _nextEntry; 426 _DoubleLinkedQueueElement<E> elementEntry = _nextEntry;
445 if (elementEntry._queue == null) { 427 if (elementEntry._queue == null) {
446 throw new ConcurrentModificationError(_sentinel._queue); 428 throw new ConcurrentModificationError(_sentinel._queue);
447 } 429 }
448 _current = elementEntry.element; 430 _current = elementEntry._element;
449 _nextEntry = elementEntry._nextLink; 431 _nextEntry = elementEntry._nextLink;
450 return true; 432 return true;
451 } 433 }
452 434
453 E get current => _current; 435 E get current => _current;
454 } 436 }
455 437
456 /** 438 /**
457 * List based [Queue]. 439 * List based [Queue].
458 * 440 *
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
833 _queue._checkModification(_modificationCount); 815 _queue._checkModification(_modificationCount);
834 if (_position == _end) { 816 if (_position == _end) {
835 _current = null; 817 _current = null;
836 return false; 818 return false;
837 } 819 }
838 _current = _queue._table[_position]; 820 _current = _queue._table[_position];
839 _position = (_position + 1) & (_queue._table.length - 1); 821 _position = (_position + 1) & (_queue._table.length - 1);
840 return true; 822 return true;
841 } 823 }
842 } 824 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698