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

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

Issue 96473003: Add Stream.timeout method. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Document zone usage. Created 7 years 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_timeout_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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 // ------------------------------------------------------------------- 7 // -------------------------------------------------------------------
8 // Core Stream types 8 // Core Stream types
9 // ------------------------------------------------------------------- 9 // -------------------------------------------------------------------
10 10
(...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 return new _TakeStream(this, count); 642 return new _TakeStream(this, count);
643 } 643 }
644 644
645 /** 645 /**
646 * Forwards data events while [test] is successful. 646 * Forwards data events while [test] is successful.
647 * 647 *
648 * The returned stream provides the same events as this stream as long 648 * The returned stream provides the same events as this stream as long
649 * as [test] returns [:true:] for the event data. The stream is done 649 * as [test] returns [:true:] for the event data. The stream is done
650 * when either this stream is done, or when this stream first provides 650 * when either this stream is done, or when this stream first provides
651 * a value that [test] doesn't accept. 651 * a value that [test] doesn't accept.
652 * 652 *
653 * Stops listening to the stream after the accepted elements. 653 * Stops listening to the stream after the accepted elements.
654 * 654 *
655 * Internally the method cancels its subscription after these elements. This 655 * Internally the method cancels its subscription after these elements. This
656 * means that single-subscription (non-broadcast) streams are closed and 656 * means that single-subscription (non-broadcast) streams are closed and
657 * cannot be reused after a call to this method. 657 * cannot be reused after a call to this method.
658 */ 658 */
659 Stream<T> takeWhile(bool test(T element)) { 659 Stream<T> takeWhile(bool test(T element)) {
660 return new _TakeWhileStream(this, test); 660 return new _TakeWhileStream(this, test);
661 } 661 }
662 662
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 } 953 }
954 index -= 1; 954 index -= 1;
955 }, 955 },
956 onError: future._completeError, 956 onError: future._completeError,
957 onDone: () { 957 onDone: () {
958 future._completeError(new RangeError.value(index)); 958 future._completeError(new RangeError.value(index));
959 }, 959 },
960 cancelOnError: true); 960 cancelOnError: true);
961 return future; 961 return future;
962 } 962 }
963
964 /**
965 * Creates a new stream with the same events as this stream.
966 *
967 * Whenever more than [timeLimit] passes between two events from this stream,
968 * the [onTimeout] function is called.
969 *
970 * The countdown doesn't start until the returned stream is listened to.
971 * The countdown is reset every time an event is forwarded from this stream,
972 * or when the stream is paused and resumed.
973 *
974 * The [onTimeout] function is called with one argument: an
975 * [EventSink] that allows putting events into the returned stream.
976 * This `EventSink` is only valid during the call to `onTimeout`.
977 *
978 * If `onTimeout` is omitted, a timeout will just put a [TimeoutException]
979 * into the error channel of the returned stream.
980 */
981 Stream timeout(Duration timeLimit, {void onTimeout(EventSink sink)}) {
982 StreamSubscription<T> subscription;
983 _StreamController controller;
984 // The following variables are set on listen.
985 Timer timer;
986 Zone zone;
987 Function timeout;
988
989 void onData(T event) {
990 timer.cancel();
991 controller.add(event);
992 timer = zone.createTimer(timeLimit, timeout);
993 }
994 void onError(error, StackTrace stackTrace) {
995 timer.cancel();
996 controller.addError(error, stackTrace);
997 timer = zone.createTimer(timeLimit, timeout);
998 }
999 void onDone() {
1000 timer.cancel();
1001 controller.close();
1002 }
1003 controller = new _SyncStreamController(
1004 () {
1005 // This is the onListen callback for of controller.
1006 // It runs in the same zone that the subscription was created in.
1007 // Use that zone for creating timers and running the onTimeout
1008 // callback.
1009 zone = Zone.current;
1010 if (onTimeout == null) {
1011 timeout = () {
1012 controller.addError(new TimeoutException("No stream event",
1013 timeLimit));
1014 };
1015 } else {
1016 onTimeout = zone.registerUnaryCallback(onTimeout);
1017 _ControllerEventSinkWrapper wrapper =
1018 new _ControllerEventSinkWrapper(null);
1019 timeout = () {
1020 wrapper._sink = controller; // Only valid during call.
1021 zone.runUnaryGuarded(onTimeout, wrapper);
1022 wrapper._sink = null;
1023 };
1024 }
1025
1026 subscription = this.listen(onData, onError: onError, onDone: onDone);
1027 timer = zone.createTimer(timeLimit, timeout);
1028 },
1029 () {
1030 timer.cancel();
1031 subscription.pause();
1032 },
1033 () {
1034 subscription.resume();
1035 timer = zone.createTimer(timeLimit, timeout);
1036 },
1037 () {
1038 timer.cancel();
1039 Future result = subscription.cancel();
1040 subscription = null;
1041 return result;
1042 });
1043 return controller.stream;
1044 }
963 } 1045 }
964 1046
965 /** 1047 /**
966 * A control object for the subscription on a [Stream]. 1048 * A control object for the subscription on a [Stream].
967 * 1049 *
968 * When you subscribe on a [Stream] using [Stream.listen], 1050 * When you subscribe on a [Stream] using [Stream.listen],
969 * a [StreamSubscription] object is returned. This object 1051 * a [StreamSubscription] object is returned. This object
970 * is used to later unsubscribe again, or to temporarily pause 1052 * is used to later unsubscribe again, or to temporarily pause
971 * the stream's events. 1053 * the stream's events.
972 */ 1054 */
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
1275 * 1357 *
1276 * If you need to stop listening for values before the stream iterator is 1358 * If you need to stop listening for values before the stream iterator is
1277 * automatically closed, you must call [cancel] to ensure that the stream 1359 * automatically closed, you must call [cancel] to ensure that the stream
1278 * is properly closed. 1360 * is properly closed.
1279 * 1361 *
1280 * Returns a future if the cancel-operation is not completed synchronously. 1362 * Returns a future if the cancel-operation is not completed synchronously.
1281 * Otherwise returns `null`. 1363 * Otherwise returns `null`.
1282 */ 1364 */
1283 Future cancel(); 1365 Future cancel();
1284 } 1366 }
1367
1368
1369 /**
1370 * Wraps an [_EventSink] so it exposes only the [EventSink] interface.
1371 */
1372 class _ControllerEventSinkWrapper<T> implements EventSink<T> {
1373 EventSink _sink;
1374 _ControllerEventSinkWrapper(this._sink);
1375
1376 void add(T data) { _sink.add(data); }
1377 void addError(error, [StackTrace stackTrace]) {
1378 _sink.addError(error, stackTrace);
1379 }
1380 void close() { _sink.close(); }
1381 }
OLDNEW
« no previous file with comments | « no previous file | tests/lib/async/stream_timeout_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698