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

Side by Side Diff: pkg/sequence_zip/lib/stream_zip.dart

Issue 18015002: Add package with iterable and stream "zipping" functionality. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address review comments. More tests. Created 7 years, 5 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 | « pkg/sequence_zip/lib/sequence_zip.dart ('k') | pkg/sequence_zip/pubspec.yaml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library stream_zip;
6
7 import "dart:async";
8
9 /**
10 * A stream that combines the values of other streams.
11 */
12 class StreamZip extends Stream<List> {
13 final Iterable<Stream> _streams;
14 StreamZip(Iterable<Stream> streams) : _streams = streams;
15
16 StreamSubscription<List> listen(void onData(List data), {
17 void onError(Object error),
18 void onDone(),
19 bool cancelOnError}) {
20 cancelOnError = identical(true, cancelOnError);
21 List<StreamSubscription> subscriptions = <StreamSubscription>[];
22 StreamController controller;
23 List current;
24 int dataCount = 0;
25
26 /// Called for each data from a subscription in [subscriptions].
27 void handleData(int index, data) {
28 current[index] = data;
29 dataCount++;
30 if (dataCount == subscriptions.length) {
31 List data = current;
32 current = new List(subscriptions.length);
33 dataCount = 0;
34 for (int i = 0; i < subscriptions.length; i++) {
35 if (i != index) subscriptions[i].resume();
36 }
37 controller.add(data);
38 } else {
39 subscriptions[index].pause();
40 }
41 }
42
43 /// Called for each error from a subscription in [subscriptons].
44 /// Except if [cancelOnError] is true, in which case the function below
45 /// is used instead.
46 void handleError(Object error) {
47 controller.addError(error);
48 }
49
50 /// Called when a subscription has an error and [cancelOnError] is true.
51 ///
52 /// Prematurely cancels all subscriptions since we know that we won't
53 /// be needing any more values.
54 void handleErrorCancel(Object error) {
55 for (int i = 0; i < subscriptions.length; i++) {
56 subscriptions[i].cancel();
57 }
58 controller.addError(error);
59 }
60
61 void handleDone() {
62 for (int i = 0; i < subscriptions.length; i++) {
63 subscriptions[i].cancel();
64 }
65 controller.close();
66 }
67
68 try {
69 for (Stream stream in _streams) {
70 int index = subscriptions.length;
71 subscriptions.add(stream.listen(
72 (data) { handleData(index, data); },
73 onError: cancelOnError ? handleError : handleErrorCancel,
74 onDone: handleDone,
75 cancelOnError: cancelOnError));
76 }
77 } catch (e) {
78 for (int i = subscriptions.length - 1; i >= 0; i--) {
79 subscriptions[i].cancel();
80 }
81 rethrow;
82 }
83
84 current = new List(subscriptions.length);
85
86 controller = new StreamController<List>(
87 onPause: () {
88 for (int i = 0; i < subscriptions.length; i++) {
89 // This may pause some subscriptions more than once.
90 // These will not be resumed by onResume below, but must wait for the
91 // next round.
92 subscriptions[i].pause();
93 }
94 },
95 onResume: () {
96 for (int i = 0; i < subscriptions.length; i++) {
97 subscriptions[i].resume();
98 }
99 },
100 onCancel: () {
101 for (int i = 0; i < subscriptions.length; i++) {
102 // Canceling more than once is safe.
103 subscriptions[i].cancel();
104 }
105 }
106 );
107
108 if (subscriptions.isEmpty) {
109 controller.close();
110 }
111 return controller.stream.listen(onData,
112 onError: onError,
113 onDone: onDone,
114 cancelOnError: cancelOnError);
115 }
116 }
OLDNEW
« no previous file with comments | « pkg/sequence_zip/lib/sequence_zip.dart ('k') | pkg/sequence_zip/pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698