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

Side by Side Diff: sdk/lib/async/stream_pipe.dart

Issue 920373003: Fix behavior when listening multiple times to a broadcast take/skip stream. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix typo Created 5 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/lib/async/stream_transformation_broadcast_test.dart » ('j') | 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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.async; 5 part of dart.async;
6 6
7 /** Runs user code and takes actions depending on success or failure. */ 7 /** Runs user code and takes actions depending on success or failure. */
8 _runUserCode(userCode(), 8 _runUserCode(userCode(),
9 onSuccess(value), 9 onSuccess(value),
10 onError(error, StackTrace stackTrace)) { 10 onError(error, StackTrace stackTrace)) {
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 return; 301 return;
302 } 302 }
303 } else { 303 } else {
304 sink._addError(error, stackTrace); 304 sink._addError(error, stackTrace);
305 } 305 }
306 } 306 }
307 } 307 }
308 308
309 309
310 class _TakeStream<T> extends _ForwardingStream<T, T> { 310 class _TakeStream<T> extends _ForwardingStream<T, T> {
311 int _remaining; 311 final int _count;
312 312
313 _TakeStream(Stream<T> source, int count) 313 _TakeStream(Stream<T> source, int count)
314 : this._remaining = count, super(source) { 314 : this._count = count, super(source) {
315 // This test is done early to avoid handling an async error 315 // This test is done early to avoid handling an async error
316 // in the _handleData method. 316 // in the _handleData method.
317 if (count is! int) throw new ArgumentError(count); 317 if (count is! int) throw new ArgumentError(count);
318 } 318 }
319 319
320 StreamSubscription<T> _createSubscription(
321 void onData(T data),
322 Function onError,
323 void onDone(),
324 bool cancelOnError) {
325 return new _StateStreamSubscription<T>(
326 this, onData, onError, onDone, cancelOnError, _count);
327 }
328
320 void _handleData(T inputEvent, _EventSink<T> sink) { 329 void _handleData(T inputEvent, _EventSink<T> sink) {
321 if (_remaining > 0) { 330 _StateStreamSubscription subscription = sink;
331 int count = subscription._count;
332 if (count > 0) {
322 sink._add(inputEvent); 333 sink._add(inputEvent);
323 _remaining -= 1; 334 count -= 1;
324 if (_remaining == 0) { 335 subscription._count = count;
336 if (count == 0) {
325 // Closing also unsubscribes all subscribers, which unsubscribes 337 // Closing also unsubscribes all subscribers, which unsubscribes
326 // this from source. 338 // this from source.
327 sink._close(); 339 sink._close();
328 } 340 }
329 } 341 }
330 } 342 }
331 } 343 }
332 344
345 /**
346 * A [_ForwardingStreamSubscription] with one extra state field.
347 *
348 * Use by several different classes, some storing an integer, others a bool.
349 */
350 class _StateStreamSubscription<T> extends _ForwardingStreamSubscription<T, T> {
351 // Raw state field. Typed access provided by getters and setters below.
352 var _sharedState;
353
354 _StateStreamSubscription(_ForwardingStream stream, void onData(T data),
355 Function onError, void onDone(),
356 bool cancelOnError, this._sharedState)
357 : super(stream, onData, onError, onDone, cancelOnError);
358
359 bool get _flag => _sharedState;
360 void set _flag(bool flag) { _sharedState = flag; }
361 int get _count => _sharedState;
362 void set _count(int count) { _sharedState = count; }
363 }
364
333 365
334 class _TakeWhileStream<T> extends _ForwardingStream<T, T> { 366 class _TakeWhileStream<T> extends _ForwardingStream<T, T> {
335 final _Predicate<T> _test; 367 final _Predicate<T> _test;
336 368
337 _TakeWhileStream(Stream<T> source, bool test(T value)) 369 _TakeWhileStream(Stream<T> source, bool test(T value))
338 : this._test = test, super(source); 370 : this._test = test, super(source);
339 371
340 void _handleData(T inputEvent, _EventSink<T> sink) { 372 void _handleData(T inputEvent, _EventSink<T> sink) {
341 bool satisfies; 373 bool satisfies;
342 try { 374 try {
343 satisfies = _test(inputEvent); 375 satisfies = _test(inputEvent);
344 } catch (e, s) { 376 } catch (e, s) {
345 _addErrorWithReplacement(sink, e, s); 377 _addErrorWithReplacement(sink, e, s);
346 // The test didn't say true. Didn't say false either, but we stop anyway. 378 // The test didn't say true. Didn't say false either, but we stop anyway.
347 sink._close(); 379 sink._close();
348 return; 380 return;
349 } 381 }
350 if (satisfies) { 382 if (satisfies) {
351 sink._add(inputEvent); 383 sink._add(inputEvent);
352 } else { 384 } else {
353 sink._close(); 385 sink._close();
354 } 386 }
355 } 387 }
356 } 388 }
357 389
358 class _SkipStream<T> extends _ForwardingStream<T, T> { 390 class _SkipStream<T> extends _ForwardingStream<T, T> {
359 int _remaining; 391 final int _count;
360 392
361 _SkipStream(Stream<T> source, int count) 393 _SkipStream(Stream<T> source, int count)
362 : this._remaining = count, super(source) { 394 : this._count = count, super(source) {
363 // This test is done early to avoid handling an async error 395 // This test is done early to avoid handling an async error
364 // in the _handleData method. 396 // in the _handleData method.
365 if (count is! int || count < 0) throw new ArgumentError(count); 397 if (count is! int || count < 0) throw new ArgumentError(count);
366 } 398 }
367 399
400 StreamSubscription<T> _createSubscription(
401 void onData(T data),
402 Function onError,
403 void onDone(),
404 bool cancelOnError) {
405 return new _StateStreamSubscription<T>(
406 this, onData, onError, onDone, cancelOnError, _count);
407 }
408
368 void _handleData(T inputEvent, _EventSink<T> sink) { 409 void _handleData(T inputEvent, _EventSink<T> sink) {
369 if (_remaining > 0) { 410 _StateStreamSubscription subscription = sink;
370 _remaining--; 411 int count = subscription._count;
412 if (count > 0) {
413 subscription._count = count - 1;
371 return; 414 return;
372 } 415 }
373 sink._add(inputEvent); 416 sink._add(inputEvent);
374 } 417 }
375 } 418 }
376 419
377 class _SkipWhileStream<T> extends _ForwardingStream<T, T> { 420 class _SkipWhileStream<T> extends _ForwardingStream<T, T> {
378 final _Predicate<T> _test; 421 final _Predicate<T> _test;
379 bool _hasFailed = false;
380 422
381 _SkipWhileStream(Stream<T> source, bool test(T value)) 423 _SkipWhileStream(Stream<T> source, bool test(T value))
382 : this._test = test, super(source); 424 : this._test = test, super(source);
383 425
426 StreamSubscription<T> _createSubscription(
427 void onData(T data),
428 Function onError,
429 void onDone(),
430 bool cancelOnError) {
431 return new _StateStreamSubscription<T>(
432 this, onData, onError, onDone, cancelOnError, false);
433 }
434
384 void _handleData(T inputEvent, _EventSink<T> sink) { 435 void _handleData(T inputEvent, _EventSink<T> sink) {
385 if (_hasFailed) { 436 _StateStreamSubscription subscription = sink;
437 bool hasFailed = subscription._flag;
438 if (hasFailed) {
386 sink._add(inputEvent); 439 sink._add(inputEvent);
387 return; 440 return;
388 } 441 }
389 bool satisfies; 442 bool satisfies;
390 try { 443 try {
391 satisfies = _test(inputEvent); 444 satisfies = _test(inputEvent);
392 } catch (e, s) { 445 } catch (e, s) {
393 _addErrorWithReplacement(sink, e, s); 446 _addErrorWithReplacement(sink, e, s);
394 // A failure to return a boolean is considered "not matching". 447 // A failure to return a boolean is considered "not matching".
395 _hasFailed = true; 448 subscription._flag = true;
396 return; 449 return;
397 } 450 }
398 if (!satisfies) { 451 if (!satisfies) {
399 _hasFailed = true; 452 subscription._flag = true;
400 sink._add(inputEvent); 453 sink._add(inputEvent);
401 } 454 }
402 } 455 }
403 } 456 }
404 457
405 typedef bool _Equality<T>(T a, T b); 458 typedef bool _Equality<T>(T a, T b);
406 459
407 class _DistinctStream<T> extends _ForwardingStream<T, T> { 460 class _DistinctStream<T> extends _ForwardingStream<T, T> {
408 static var _SENTINEL = new Object(); 461 static var _SENTINEL = new Object();
409 462
(...skipping 19 matching lines...) Expand all
429 _addErrorWithReplacement(sink, e, s); 482 _addErrorWithReplacement(sink, e, s);
430 return null; 483 return null;
431 } 484 }
432 if (!isEqual) { 485 if (!isEqual) {
433 sink._add(inputEvent); 486 sink._add(inputEvent);
434 _previous = inputEvent; 487 _previous = inputEvent;
435 } 488 }
436 } 489 }
437 } 490 }
438 } 491 }
OLDNEW
« no previous file with comments | « no previous file | tests/lib/async/stream_transformation_broadcast_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698