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

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

Issue 295913003: Make Stream.where, etc., be documented as inheriting broadcast state. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add issue number for co19 status changes. Created 6 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | sdk/lib/async/stream_transformers.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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 * itself when the listener is unsubscribed, even if the stream wasn't done. 42 * itself when the listener is unsubscribed, even if the stream wasn't done.
43 * 43 *
44 * Single-subscription streams are generally used for streaming parts of 44 * Single-subscription streams are generally used for streaming parts of
45 * contiguous data like file I/O. 45 * contiguous data like file I/O.
46 * 46 *
47 * A broadcast stream allows any number of listeners, and it fires 47 * A broadcast stream allows any number of listeners, and it fires
48 * its events when they are ready, whether there are listeners or not. 48 * its events when they are ready, whether there are listeners or not.
49 * 49 *
50 * Broadcast streams are used for independent events/observers. 50 * Broadcast streams are used for independent events/observers.
51 * 51 *
52 * Stream transformations, such as [where] and [skip], always return 52 * Stream transformations, such as [where] and [skip],
53 * non-broadcast streams. If several listeners want to listen to the returned 53 * return the same type of stream as the one the method was called on,
54 * unless otherwise noted.
55 *
56 * If several listeners want to listen to the returned
54 * stream, use [asBroadcastStream] to create a broadcast stream on top of the 57 * stream, use [asBroadcastStream] to create a broadcast stream on top of the
55 * non-broadcast stream. 58 * non-broadcast stream.
56 * 59 *
57 * The default implementation of [isBroadcast] returns false. 60 * The default implementation of [isBroadcast] returns false.
58 * A broadcast stream inheriting from [Stream] must override [isBroadcast] 61 * A broadcast stream inheriting from [Stream] must override [isBroadcast]
59 * to return [:true:]. 62 * to return [:true:].
60 */ 63 */
61 abstract class Stream<T> { 64 abstract class Stream<T> {
62 Stream(); 65 Stream();
63 66
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 } 199 }
197 200
198 /** 201 /**
199 * Reports whether this stream is a broadcast stream. 202 * Reports whether this stream is a broadcast stream.
200 */ 203 */
201 bool get isBroadcast => false; 204 bool get isBroadcast => false;
202 205
203 /** 206 /**
204 * Returns a multi-subscription stream that produces the same events as this. 207 * Returns a multi-subscription stream that produces the same events as this.
205 * 208 *
206 * If this stream is already a broadcast stream, it is returned unmodified. 209 * The returned stream will subscribe to this stream when its first
207 *
208 * If this stream is single-subscription, return a new stream that allows
209 * multiple subscribers. It will subscribe to this stream when its first
210 * subscriber is added, and will stay subscribed until this stream ends, 210 * subscriber is added, and will stay subscribed until this stream ends,
211 * or a callback cancels the subscription. 211 * or a callback cancels the subscription.
212 * 212 *
213 * If [onListen] is provided, it is called with a subscription-like object 213 * If [onListen] is provided, it is called with a subscription-like object
214 * that represents the underlying subscription to this stream. It is 214 * that represents the underlying subscription to this stream. It is
215 * possible to pause, resume or cancel the subscription during the call 215 * possible to pause, resume or cancel the subscription during the call
216 * to [onListen]. It is not possible to change the event handlers, including 216 * to [onListen]. It is not possible to change the event handlers, including
217 * using [StreamSubscription.asFuture]. 217 * using [StreamSubscription.asFuture].
218 * 218 *
219 * If [onCancel] is provided, it is called in a similar way to [onListen] 219 * If [onCancel] is provided, it is called in a similar way to [onListen]
220 * when the returned stream stops having listener. If it later gets 220 * when the returned stream stops having listener. If it later gets
221 * a new listener, the [onListen] function is called again. 221 * a new listener, the [onListen] function is called again.
222 * 222 *
223 * Use the callbacks, for example, for pausing the underlying subscription 223 * Use the callbacks, for example, for pausing the underlying subscription
224 * while having no subscribers to prevent losing events, or canceling the 224 * while having no subscribers to prevent losing events, or canceling the
225 * subscription when there are no listeners. 225 * subscription when there are no listeners.
226 */ 226 */
227 Stream<T> asBroadcastStream({ 227 Stream<T> asBroadcastStream({
228 void onListen(StreamSubscription<T> subscription), 228 void onListen(StreamSubscription<T> subscription),
229 void onCancel(StreamSubscription<T> subscription) }) { 229 void onCancel(StreamSubscription<T> subscription) }) {
230 if (isBroadcast) return this;
231 return new _AsBroadcastStream<T>(this, onListen, onCancel); 230 return new _AsBroadcastStream<T>(this, onListen, onCancel);
232 } 231 }
233 232
234 /** 233 /**
235 * Adds a subscription to this stream. 234 * Adds a subscription to this stream.
236 * 235 *
237 * On each data event from this stream, the subscriber's [onData] handler 236 * On each data event from this stream, the subscriber's [onData] handler
238 * is called. If [onData] is null, nothing happens. 237 * is called. If [onData] is null, nothing happens.
239 * 238 *
240 * On errors from this stream, the [onError] handler is given a 239 * On errors from this stream, the [onError] handler is given a
(...skipping 14 matching lines...) Expand all
255 { Function onError, 254 { Function onError,
256 void onDone(), 255 void onDone(),
257 bool cancelOnError}); 256 bool cancelOnError});
258 257
259 /** 258 /**
260 * Creates a new stream from this stream that discards some data events. 259 * Creates a new stream from this stream that discards some data events.
261 * 260 *
262 * The new stream sends the same error and done events as this stream, 261 * The new stream sends the same error and done events as this stream,
263 * but it only sends the data events that satisfy the [test]. 262 * but it only sends the data events that satisfy the [test].
264 * 263 *
265 * The returned stream is not a broadcast stream, even if this stream is. 264 * The returned stream is a broadcast stream if this stream is.
266 */ 265 */
267 Stream<T> where(bool test(T event)) { 266 Stream<T> where(bool test(T event)) {
268 return new _WhereStream<T>(this, test); 267 return new _WhereStream<T>(this, test);
269 } 268 }
270 269
271 /** 270 /**
272 * Creates a new stream that converts each element of this stream 271 * Creates a new stream that converts each element of this stream
273 * to a new value using the [convert] function. 272 * to a new value using the [convert] function.
274 * 273 *
275 * The returned stream is not a broadcast stream, even if this stream is. 274 * The returned stream is a broadcast stream if this stream is.
276 */ 275 */
277 Stream map(convert(T event)) { 276 Stream map(convert(T event)) {
278 return new _MapStream<T, dynamic>(this, convert); 277 return new _MapStream<T, dynamic>(this, convert);
279 } 278 }
280 279
281 /** 280 /**
282 * Creates a new stream with each data event of this stream asynchronously 281 * Creates a new stream with each data event of this stream asynchronously
283 * mapped to a new event. 282 * mapped to a new event.
284 * 283 *
285 * This acts like [map], except that [convert] may return a [Future], 284 * This acts like [map], except that [convert] may return a [Future],
286 * and in that case, the stream waits for that future to complete before 285 * and in that case, the stream waits for that future to complete before
287 * continuing with its result. 286 * continuing with its result.
287 *
288 * The returned stream is a broadcast stream if this stream is.
288 */ 289 */
289 Stream asyncMap(convert(T event)) { 290 Stream asyncMap(convert(T event)) {
290 StreamController controller; 291 StreamController controller;
291 StreamSubscription subscription; 292 StreamSubscription subscription;
292 controller = new StreamController( 293 void onListen () {
293 onListen: () { 294 var add = controller.add;
294 var add = controller.add; 295 var addError = controller.addError;
295 var addError = controller.addError; 296 subscription = this.listen(
296 subscription = this.listen( 297 (T event) {
297 (T event) { 298 var newValue;
298 var newValue; 299 try {
299 try { 300 newValue = convert(event);
300 newValue = convert(event); 301 } catch (e, s) {
301 } catch (e, s) { 302 controller.addError(e, s);
302 controller.addError(e, s); 303 return;
303 return; 304 }
304 } 305 if (newValue is Future) {
305 if (newValue is Future) { 306 subscription.pause();
306 subscription.pause(); 307 newValue.then(add, onError: addError)
307 newValue.then(add, onError: addError) 308 .whenComplete(subscription.resume);
308 .whenComplete(subscription.resume); 309 } else {
309 } else { 310 controller.add(newValue);
310 controller.add(newValue); 311 }
311 } 312 },
312 }, 313 onError: addError,
313 onError: addError, 314 onDone: controller.close
314 onDone: controller.close 315 );
315 ); 316 }
316 }, 317 if (this.isBroadcast) {
317 onPause: () { subscription.pause(); }, 318 controller = new StreamController.broadcast(
318 onResume: () { subscription.resume(); }, 319 onListen: onListen,
319 onCancel: () { subscription.cancel(); }, 320 onCancel: () { subscription.cancel(); },
320 sync: true 321 sync: true
321 ); 322 );
323 } else {
324 controller = new StreamController(
325 onListen: onListen,
326 onPause: () { subscription.pause(); },
327 onResume: () { subscription.resume(); },
328 onCancel: () { subscription.cancel(); },
329 sync: true
330 );
331 }
322 return controller.stream; 332 return controller.stream;
323 } 333 }
324 334
325 /** 335 /**
326 * Creates a new stream with the events of a stream per original event. 336 * Creates a new stream with the events of a stream per original event.
327 * 337 *
328 * This acts like [expand], except that [convert] returns a [Stream] 338 * This acts like [expand], except that [convert] returns a [Stream]
329 * instead of an [Iterable]. 339 * instead of an [Iterable].
330 * The events of the returned stream becomes the events of the returned 340 * The events of the returned stream becomes the events of the returned
331 * stream, in the order they are produced. 341 * stream, in the order they are produced.
332 * 342 *
333 * If [convert] returns `null`, no value is put on the output stream, 343 * If [convert] returns `null`, no value is put on the output stream,
334 * just as if it returned an empty stream. 344 * just as if it returned an empty stream.
345 *
346 * The returned stream is a broadcast stream if this stream is.
335 */ 347 */
336 Stream asyncExpand(Stream convert(T event)) { 348 Stream asyncExpand(Stream convert(T event)) {
337 StreamController controller; 349 StreamController controller;
338 StreamSubscription subscription; 350 StreamSubscription subscription;
339 controller = new StreamController( 351 void onListen() {
340 onListen: () { 352 subscription = this.listen(
341 subscription = this.listen( 353 (T event) {
342 (T event) { 354 Stream newStream;
343 Stream newStream; 355 try {
344 try { 356 newStream = convert(event);
345 newStream = convert(event); 357 } catch (e, s) {
346 } catch (e, s) { 358 controller.addError(e, s);
347 controller.addError(e, s); 359 return;
348 return; 360 }
349 } 361 if (newStream != null) {
350 if (newStream != null) { 362 subscription.pause();
351 subscription.pause(); 363 controller.addStream(newStream)
352 controller.addStream(newStream) 364 .whenComplete(subscription.resume);
353 .whenComplete(subscription.resume); 365 }
354 } 366 },
355 }, 367 onError: controller.addError,
356 onError: controller.addError, 368 onDone: controller.close
357 onDone: controller.close 369 );
358 ); 370 }
359 }, 371 if (this.isBroadcast) {
360 onPause: () { subscription.pause(); }, 372 controller = new StreamController.broadcast(
361 onResume: () { subscription.resume(); }, 373 onListen: onListen,
362 onCancel: () { subscription.cancel(); }, 374 onCancel: () { subscription.cancel(); },
363 sync: true 375 sync: true
364 ); 376 );
377 } else {
378 controller = new StreamController(
379 onListen: onListen,
380 onPause: () { subscription.pause(); },
381 onResume: () { subscription.resume(); },
382 onCancel: () { subscription.cancel(); },
383 sync: true
384 );
385 }
365 return controller.stream; 386 return controller.stream;
366 } 387 }
367 388
368 /** 389 /**
369 * Creates a wrapper Stream that intercepts some errors from this stream. 390 * Creates a wrapper Stream that intercepts some errors from this stream.
370 * 391 *
371 * If this stream sends an error that matches [test], then it is intercepted 392 * If this stream sends an error that matches [test], then it is intercepted
372 * by the [handle] function. 393 * by the [handle] function.
373 * 394 *
374 * The [onError] callback must be of type `void onError(error)` or 395 * The [onError] callback must be of type `void onError(error)` or
375 * `void onError(error, StackTrace stackTrace)`. Depending on the function 396 * `void onError(error, StackTrace stackTrace)`. Depending on the function
376 * type the the stream either invokes [onError] with or without a stack 397 * type the the stream either invokes [onError] with or without a stack
377 * trace. The stack trace argument might be `null` if the stream itself 398 * trace. The stack trace argument might be `null` if the stream itself
378 * received an error without stack trace. 399 * received an error without stack trace.
379 * 400 *
380 * An asynchronous error [:e:] is matched by a test function if [:test(e):] 401 * An asynchronous error [:e:] is matched by a test function if [:test(e):]
381 * returns true. If [test] is omitted, every error is considered matching. 402 * returns true. If [test] is omitted, every error is considered matching.
382 * 403 *
383 * If the error is intercepted, the [handle] function can decide what to do 404 * If the error is intercepted, the [handle] function can decide what to do
384 * with it. It can throw if it wants to raise a new (or the same) error, 405 * with it. It can throw if it wants to raise a new (or the same) error,
385 * or simply return to make the stream forget the error. 406 * or simply return to make the stream forget the error.
386 * 407 *
387 * If you need to transform an error into a data event, use the more generic 408 * If you need to transform an error into a data event, use the more generic
388 * [Stream.transform] to handle the event by writing a data event to 409 * [Stream.transform] to handle the event by writing a data event to
389 * the output sink 410 * the output sink
390 * 411 *
391 * The returned stream is not a broadcast stream, even if this stream is. 412 * The returned stream is a broadcast stream if this stream is.
392 */ 413 */
393 Stream<T> handleError(Function onError, { bool test(error) }) { 414 Stream<T> handleError(Function onError, { bool test(error) }) {
394 return new _HandleErrorStream<T>(this, onError, test); 415 return new _HandleErrorStream<T>(this, onError, test);
395 } 416 }
396 417
397 /** 418 /**
398 * Creates a new stream from this stream that converts each element 419 * Creates a new stream from this stream that converts each element
399 * into zero or more events. 420 * into zero or more events.
400 * 421 *
401 * Each incoming event is converted to an [Iterable] of new events, 422 * Each incoming event is converted to an [Iterable] of new events,
402 * and each of these new events are then sent by the returned stream 423 * and each of these new events are then sent by the returned stream
403 * in order. 424 * in order.
404 * 425 *
405 * The returned stream is not a broadcast stream, even if this stream is. 426 * The returned stream is a broadcast stream if this stream is.
406 */ 427 */
407 Stream expand(Iterable convert(T value)) { 428 Stream expand(Iterable convert(T value)) {
408 return new _ExpandStream<T, dynamic>(this, convert); 429 return new _ExpandStream<T, dynamic>(this, convert);
409 } 430 }
410 431
411 /** 432 /**
412 * Binds this stream as the input of the provided [StreamConsumer]. 433 * Binds this stream as the input of the provided [StreamConsumer].
413 */ 434 */
414 Future pipe(StreamConsumer<T> streamConsumer) { 435 Future pipe(StreamConsumer<T> streamConsumer) {
415 return streamConsumer.addStream(this).then((_) => streamConsumer.close()); 436 return streamConsumer.addStream(this).then((_) => streamConsumer.close());
416 } 437 }
417 438
418 /** 439 /**
419 * Chains this stream as the input of the provided [StreamTransformer]. 440 * Chains this stream as the input of the provided [StreamTransformer].
420 * 441 *
421 * Returns the result of [:streamTransformer.bind:] itself. 442 * Returns the result of [:streamTransformer.bind:] itself.
443 *
444 * The `streamTransformer` can decide whether it wants to return a
445 * broadcast stream or not.
422 */ 446 */
423 Stream transform(StreamTransformer<T, dynamic> streamTransformer) { 447 Stream transform(StreamTransformer<T, dynamic> streamTransformer) {
424 return streamTransformer.bind(this); 448 return streamTransformer.bind(this);
425 } 449 }
426 450
427 /** 451 /**
428 * Reduces a sequence of values by repeatedly applying [combine]. 452 * Reduces a sequence of values by repeatedly applying [combine].
429 */ 453 */
430 Future<T> reduce(T combine(T previous, T element)) { 454 Future<T> reduce(T combine(T previous, T element)) {
431 _Future<T> result = new _Future<T>(); 455 _Future<T> result = new _Future<T>();
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 * If this stream produces fewer than [count] values before it's done, 755 * If this stream produces fewer than [count] values before it's done,
732 * so will the returned stream. 756 * so will the returned stream.
733 * 757 *
734 * Stops listening to the stream after the first [n] elements have been 758 * Stops listening to the stream after the first [n] elements have been
735 * received. 759 * received.
736 * 760 *
737 * Internally the method cancels its subscription after these elements. This 761 * Internally the method cancels its subscription after these elements. This
738 * means that single-subscription (non-broadcast) streams are closed and 762 * means that single-subscription (non-broadcast) streams are closed and
739 * cannot be reused after a call to this method. 763 * cannot be reused after a call to this method.
740 * 764 *
741 * The returned stream is not a broadcast stream, even if this stream is. 765 * The returned stream is a broadcast stream if this stream is.
742 */ 766 */
743 Stream<T> take(int count) { 767 Stream<T> take(int count) {
744 return new _TakeStream(this, count); 768 return new _TakeStream(this, count);
745 } 769 }
746 770
747 /** 771 /**
748 * Forwards data events while [test] is successful. 772 * Forwards data events while [test] is successful.
749 * 773 *
750 * The returned stream provides the same events as this stream as long 774 * The returned stream provides the same events as this stream as long
751 * as [test] returns [:true:] for the event data. The stream is done 775 * as [test] returns [:true:] for the event data. The stream is done
752 * when either this stream is done, or when this stream first provides 776 * when either this stream is done, or when this stream first provides
753 * a value that [test] doesn't accept. 777 * a value that [test] doesn't accept.
754 * 778 *
755 * Stops listening to the stream after the accepted elements. 779 * Stops listening to the stream after the accepted elements.
756 * 780 *
757 * Internally the method cancels its subscription after these elements. This 781 * Internally the method cancels its subscription after these elements. This
758 * means that single-subscription (non-broadcast) streams are closed and 782 * means that single-subscription (non-broadcast) streams are closed and
759 * cannot be reused after a call to this method. 783 * cannot be reused after a call to this method.
760 * 784 *
761 * The returned stream is not a broadcast stream, even if this stream is. 785 * The returned stream is a broadcast stream if this stream is.
762 */ 786 */
763 Stream<T> takeWhile(bool test(T element)) { 787 Stream<T> takeWhile(bool test(T element)) {
764 return new _TakeWhileStream(this, test); 788 return new _TakeWhileStream(this, test);
765 } 789 }
766 790
767 /** 791 /**
768 * Skips the first [count] data events from this stream. 792 * Skips the first [count] data events from this stream.
769 * 793 *
770 * The returned stream is not a broadcast stream, even if this stream is. 794 * The returned stream is a broadcast stream if this stream is.
771 */ 795 */
772 Stream<T> skip(int count) { 796 Stream<T> skip(int count) {
773 return new _SkipStream(this, count); 797 return new _SkipStream(this, count);
774 } 798 }
775 799
776 /** 800 /**
777 * Skip data events from this stream while they are matched by [test]. 801 * Skip data events from this stream while they are matched by [test].
778 * 802 *
779 * Error and done events are provided by the returned stream unmodified. 803 * Error and done events are provided by the returned stream unmodified.
780 * 804 *
781 * Starting with the first data event where [test] returns false for the 805 * Starting with the first data event where [test] returns false for the
782 * event data, the returned stream will have the same events as this stream. 806 * event data, the returned stream will have the same events as this stream.
783 * 807 *
784 * The returned stream is not a broadcast stream, even if this stream is. 808 * The returned stream is a broadcast stream if this stream is.
785 */ 809 */
786 Stream<T> skipWhile(bool test(T element)) { 810 Stream<T> skipWhile(bool test(T element)) {
787 return new _SkipWhileStream(this, test); 811 return new _SkipWhileStream(this, test);
788 } 812 }
789 813
790 /** 814 /**
791 * Skips data events if they are equal to the previous data event. 815 * Skips data events if they are equal to the previous data event.
792 * 816 *
793 * The returned stream provides the same events as this stream, except 817 * The returned stream provides the same events as this stream, except
794 * that it never provides two consequtive data events that are equal. 818 * that it never provides two consequtive data events that are equal.
795 * 819 *
796 * Equality is determined by the provided [equals] method. If that is 820 * Equality is determined by the provided [equals] method. If that is
797 * omitted, the '==' operator on the last provided data element is used. 821 * omitted, the '==' operator on the last provided data element is used.
798 * 822 *
799 * The returned stream is not a broadcast stream, even if this stream is. 823 * The returned stream is a broadcast stream if this stream is.
800 */ 824 */
801 Stream<T> distinct([bool equals(T previous, T next)]) { 825 Stream<T> distinct([bool equals(T previous, T next)]) {
802 return new _DistinctStream(this, equals); 826 return new _DistinctStream(this, equals);
803 } 827 }
804 828
805 /** 829 /**
806 * Returns the first element of the stream. 830 * Returns the first element of the stream.
807 * 831 *
808 * Stops listening to the stream after the first element has been received. 832 * Stops listening to the stream after the first element has been received.
809 * 833 *
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
1081 * The countdown is reset every time an event is forwarded from this stream, 1105 * The countdown is reset every time an event is forwarded from this stream,
1082 * or when the stream is paused and resumed. 1106 * or when the stream is paused and resumed.
1083 * 1107 *
1084 * The [onTimeout] function is called with one argument: an 1108 * The [onTimeout] function is called with one argument: an
1085 * [EventSink] that allows putting events into the returned stream. 1109 * [EventSink] that allows putting events into the returned stream.
1086 * This `EventSink` is only valid during the call to `onTimeout`. 1110 * This `EventSink` is only valid during the call to `onTimeout`.
1087 * 1111 *
1088 * If `onTimeout` is omitted, a timeout will just put a [TimeoutException] 1112 * If `onTimeout` is omitted, a timeout will just put a [TimeoutException]
1089 * into the error channel of the returned stream. 1113 * into the error channel of the returned stream.
1090 * 1114 *
1091 * The returned stream is not a broadcast stream, even if this stream is. 1115 * The returned stream is a broadcast stream if this stream is.
1092 */ 1116 */
1093 Stream timeout(Duration timeLimit, {void onTimeout(EventSink sink)}) { 1117 Stream timeout(Duration timeLimit, {void onTimeout(EventSink sink)}) {
1118 StreamController controller;
1119 // The following variables are set on listen.
1094 StreamSubscription<T> subscription; 1120 StreamSubscription<T> subscription;
1095 _StreamController controller;
1096 // The following variables are set on listen.
1097 Timer timer; 1121 Timer timer;
1098 Zone zone; 1122 Zone zone;
1099 Function timeout; 1123 Function timeout;
1100 1124
1101 void onData(T event) { 1125 void onData(T event) {
1102 timer.cancel(); 1126 timer.cancel();
1103 controller.add(event); 1127 controller.add(event);
1104 timer = zone.createTimer(timeLimit, timeout); 1128 timer = zone.createTimer(timeLimit, timeout);
1105 } 1129 }
1106 void onError(error, StackTrace stackTrace) { 1130 void onError(error, StackTrace stackTrace) {
1107 timer.cancel(); 1131 timer.cancel();
1108 controller.addError(error, stackTrace); 1132 controller.addError(error, stackTrace);
1109 timer = zone.createTimer(timeLimit, timeout); 1133 timer = zone.createTimer(timeLimit, timeout);
1110 } 1134 }
1111 void onDone() { 1135 void onDone() {
1112 timer.cancel(); 1136 timer.cancel();
1113 controller.close(); 1137 controller.close();
1114 } 1138 }
1115 controller = new _SyncStreamController( 1139 void onListen() {
1116 () { 1140 // This is the onListen callback for of controller.
1117 // This is the onListen callback for of controller. 1141 // It runs in the same zone that the subscription was created in.
1118 // It runs in the same zone that the subscription was created in. 1142 // Use that zone for creating timers and running the onTimeout
1119 // Use that zone for creating timers and running the onTimeout 1143 // callback.
1120 // callback. 1144 zone = Zone.current;
1121 zone = Zone.current; 1145 if (onTimeout == null) {
1122 if (onTimeout == null) { 1146 timeout = () {
1123 timeout = () { 1147 controller.addError(new TimeoutException("No stream event",
1124 controller.addError(new TimeoutException("No stream event", 1148 timeLimit));
1125 timeLimit)); 1149 };
1126 }; 1150 } else {
1127 } else { 1151 onTimeout = zone.registerUnaryCallback(onTimeout);
1128 onTimeout = zone.registerUnaryCallback(onTimeout); 1152 _ControllerEventSinkWrapper wrapper =
1129 _ControllerEventSinkWrapper wrapper = 1153 new _ControllerEventSinkWrapper(null);
1130 new _ControllerEventSinkWrapper(null); 1154 timeout = () {
1131 timeout = () { 1155 wrapper._sink = controller; // Only valid during call.
1132 wrapper._sink = controller; // Only valid during call. 1156 zone.runUnaryGuarded(onTimeout, wrapper);
1133 zone.runUnaryGuarded(onTimeout, wrapper); 1157 wrapper._sink = null;
1134 wrapper._sink = null; 1158 };
1135 }; 1159 }
1136 }
1137 1160
1138 subscription = this.listen(onData, onError: onError, onDone: onDone); 1161 subscription = this.listen(onData, onError: onError, onDone: onDone);
1139 timer = zone.createTimer(timeLimit, timeout); 1162 timer = zone.createTimer(timeLimit, timeout);
1140 }, 1163 }
1141 () { 1164 Future onCancel() {
1142 timer.cancel(); 1165 timer.cancel();
1143 subscription.pause(); 1166 Future result = subscription.cancel();
1144 }, 1167 subscription = null;
1145 () { 1168 return result;
1146 subscription.resume(); 1169 }
1147 timer = zone.createTimer(timeLimit, timeout); 1170 controller = isBroadcast
1148 }, 1171 ? new _SyncBroadcastStreamController(onListen, onCancel)
1149 () { 1172 : new _SyncStreamController(
1150 timer.cancel(); 1173 onListen,
1151 Future result = subscription.cancel(); 1174 () {
1152 subscription = null; 1175 // Don't null the timer, onCancel may call cancel again.
1153 return result; 1176 timer.cancel();
1154 }); 1177 subscription.pause();
1178 },
1179 () {
1180 subscription.resume();
1181 timer = zone.createTimer(timeLimit, timeout);
1182 },
1183 onCancel);
1155 return controller.stream; 1184 return controller.stream;
1156 } 1185 }
1157 } 1186 }
1158 1187
1159 /** 1188 /**
1160 * A control object for the subscription on a [Stream]. 1189 * A control object for the subscription on a [Stream].
1161 * 1190 *
1162 * When you subscribe on a [Stream] using [Stream.listen], 1191 * When you subscribe on a [Stream] using [Stream.listen],
1163 * a [StreamSubscription] object is returned. This object 1192 * a [StreamSubscription] object is returned. This object
1164 * is used to later unsubscribe again, or to temporarily pause 1193 * is used to later unsubscribe again, or to temporarily pause
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
1489 class _ControllerEventSinkWrapper<T> implements EventSink<T> { 1518 class _ControllerEventSinkWrapper<T> implements EventSink<T> {
1490 EventSink _sink; 1519 EventSink _sink;
1491 _ControllerEventSinkWrapper(this._sink); 1520 _ControllerEventSinkWrapper(this._sink);
1492 1521
1493 void add(T data) { _sink.add(data); } 1522 void add(T data) { _sink.add(data); }
1494 void addError(error, [StackTrace stackTrace]) { 1523 void addError(error, [StackTrace stackTrace]) {
1495 _sink.addError(error, stackTrace); 1524 _sink.addError(error, stackTrace);
1496 } 1525 }
1497 void close() { _sink.close(); } 1526 void close() { _sink.close(); }
1498 } 1527 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/async/stream_transformers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698