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

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

Issue 11791045: Added toMultiSubscriber on Stream. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments. Created 7 years, 11 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
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 /** 7 /**
8 * A pipe between two streams. 8 * A wrapper around a stream that allows independent subscribers.
9 * 9 *
10 * The default pipe subscribes to the [source] and sends on the 10 * By default [this] subscribes to [_source] and forwards all events to its own
11 * [stream]. 11 * subscribers. It does not subscribe until there is a subscriber, and
12 * unsubscribes again when there are no subscribers left.
12 * 13 *
13 * The events are passed through the [_handleData], [_handleError] and 14 * The events are passed through the [_handleData], [_handleError] and
14 * [_handleDone] methods. Subclasses are supposed to add handling of some of 15 * [_handleDone] methods. Subclasses are supposed to add handling of some of
15 * the events by overriding these methods. 16 * the events by overriding these methods.
16 * 17 *
17 * This class is intended for internal use only. Users can use the [PipeStream] 18 * This class is intended for internal use only.
18 * to configure similar behavior.
19 */ 19 */
20 abstract class _ForwardingStream<S, T> extends _MultiStreamImpl<T> 20 class _ForwardingMultiStream<S, T> extends _MultiStreamImpl<T> {
21 implements StreamTransformer<S, T> {
22 Stream<S> _source = null; 21 Stream<S> _source = null;
23 StreamSubscription _subscription = null; 22 StreamSubscription _subscription = null;
24 23
25 void _subscribeToSource() { 24 void _subscribeToSource() {
26 _subscription = _source.listen(this._handleData, 25 _subscription = _source.listen(this._handleData,
27 onError: this._handleError, 26 onError: this._handleError,
28 onDone: this._handleDone); 27 onDone: this._handleDone);
29 if (_isPaused) { 28 if (_isPaused) {
30 _subscription.pause(); 29 _subscription.pause();
31 } 30 }
32 } 31 }
33 32
34 Stream<T> bind(Stream<S> source) {
35 assert(_source == null);
36 _source = source;
37 if (_hasSubscribers) {
38 _subscribeToSource();
39 }
40 return this;
41 }
42
43 /** 33 /**
44 * Subscribe or unsubscribe on [source] depending on whether 34 * Subscribe or unsubscribe on [source] depending on whether
45 * [stream] has subscribers. 35 * [stream] has subscribers.
46 */ 36 */
47 void _onSubscriptionStateChange() { 37 void _onSubscriptionStateChange() {
48 if (_hasSubscribers) { 38 if (_hasSubscribers) {
49 assert(_subscription == null); 39 assert(_subscription == null);
50 if (_source != null) { 40 if (_source != null) {
51 _subscribeToSource(); 41 _subscribeToSource();
52 } 42 }
(...skipping 22 matching lines...) Expand all
75 void _handleError(AsyncError error) { 65 void _handleError(AsyncError error) {
76 _signalError(error); 66 _signalError(error);
77 } 67 }
78 68
79 void _handleDone() { 69 void _handleDone() {
80 _close(); 70 _close();
81 } 71 }
82 } 72 }
83 73
84 74
75 abstract class _ForwardingTransformer<S, T> extends _ForwardingMultiStream<S, T>
76 implements StreamTransformer<S, T> {
77 Stream<T> bind(Stream<S> source) {
78 assert(_source == null);
79 _source = source;
80 if (_hasSubscribers) {
81 _subscribeToSource();
82 }
83 return this;
84 }
85 }
86
85 // ------------------------------------------------------------------- 87 // -------------------------------------------------------------------
86 // Stream pipes used by the default Stream implementation. 88 // Stream transformers used by the default Stream implementation.
87 // ------------------------------------------------------------------- 89 // -------------------------------------------------------------------
88 90
89 typedef bool _Predicate<T>(T value); 91 typedef bool _Predicate<T>(T value);
90 92
91 class WhereStream<T> extends _ForwardingStream<T, T> { 93 class WhereStream<T> extends _ForwardingTransformer<T, T> {
92 final _Predicate<T> _test; 94 final _Predicate<T> _test;
93 95
94 WhereStream(bool test(T value)) 96 WhereStream(bool test(T value))
95 : this._test = test; 97 : this._test = test;
96 98
97 void _handleData(T inputEvent) { 99 void _handleData(T inputEvent) {
98 bool satisfies; 100 bool satisfies;
99 try { 101 try {
100 satisfies = _test(inputEvent); 102 satisfies = _test(inputEvent);
101 } catch (e, s) { 103 } catch (e, s) {
102 _signalError(new AsyncError(e, s)); 104 _signalError(new AsyncError(e, s));
103 return; 105 return;
104 } 106 }
105 if (satisfies) { 107 if (satisfies) {
106 _add(inputEvent); 108 _add(inputEvent);
107 } 109 }
108 } 110 }
109 } 111 }
110 112
111 113
112 typedef T _Transformation<S, T>(S value); 114 typedef T _Transformation<S, T>(S value);
113 115
114 /** 116 /**
115 * A stream pipe that converts data events before passing them on. 117 * A stream pipe that converts data events before passing them on.
116 */ 118 */
117 class MapStream<S, T> extends _ForwardingStream<S, T> { 119 class MapStream<S, T> extends _ForwardingTransformer<S, T> {
118 final _Transformation _transform; 120 final _Transformation _transform;
119 121
120 MapStream(T transform(S event)) 122 MapStream(T transform(S event))
121 : this._transform = transform; 123 : this._transform = transform;
122 124
123 void _handleData(S inputEvent) { 125 void _handleData(S inputEvent) {
124 T outputEvent; 126 T outputEvent;
125 try { 127 try {
126 outputEvent = _transform(inputEvent); 128 outputEvent = _transform(inputEvent);
127 } catch (e, s) { 129 } catch (e, s) {
128 _signalError(new AsyncError(e, s)); 130 _signalError(new AsyncError(e, s));
129 return; 131 return;
130 } 132 }
131 _add(outputEvent); 133 _add(outputEvent);
132 } 134 }
133 } 135 }
134 136
135 /** 137 /**
136 * A stream pipe that converts data events before passing them on. 138 * A stream pipe that converts data events before passing them on.
137 */ 139 */
138 class ExpandStream<S, T> extends _ForwardingStream<S, T> { 140 class ExpandStream<S, T> extends _ForwardingTransformer<S, T> {
139 final _Transformation<S, Iterable<T>> _expand; 141 final _Transformation<S, Iterable<T>> _expand;
140 142
141 ExpandStream(Iterable<T> expand(S event)) 143 ExpandStream(Iterable<T> expand(S event))
142 : this._expand = expand; 144 : this._expand = expand;
143 145
144 void _handleData(S inputEvent) { 146 void _handleData(S inputEvent) {
145 try { 147 try {
146 for (T value in _expand(inputEvent)) { 148 for (T value in _expand(inputEvent)) {
147 _add(value); 149 _add(value);
148 } 150 }
149 } catch (e, s) { 151 } catch (e, s) {
150 // If either _expand or iterating the generated iterator throws, 152 // If either _expand or iterating the generated iterator throws,
151 // we abort the iteration. 153 // we abort the iteration.
152 _signalError(new AsyncError(e, s)); 154 _signalError(new AsyncError(e, s));
153 } 155 }
154 } 156 }
155 } 157 }
156 158
157 159
158 typedef AsyncError _ErrorTransformation(AsyncError error); 160 typedef AsyncError _ErrorTransformation(AsyncError error);
159 161
160 /** 162 /**
161 * A stream pipe that converts or disposes error events 163 * A stream pipe that converts or disposes error events
162 * before passing them on. 164 * before passing them on.
163 */ 165 */
164 class HandleErrorStream<T> extends _ForwardingStream<T, T> { 166 class HandleErrorStream<T> extends _ForwardingTransformer<T, T> {
165 final _ErrorTransformation _transform; 167 final _ErrorTransformation _transform;
166 168
167 HandleErrorStream(AsyncError transform(AsyncError event)) 169 HandleErrorStream(AsyncError transform(AsyncError event))
168 : this._transform = transform; 170 : this._transform = transform;
169 171
170 void _handleError(AsyncError error) { 172 void _handleError(AsyncError error) {
171 try { 173 try {
172 error = _transform(error); 174 error = _transform(error);
173 if (error == null) return; 175 if (error == null) return;
174 } catch (e, s) { 176 } catch (e, s) {
(...skipping 10 matching lines...) Expand all
185 187
186 /** 188 /**
187 * A stream pipe that intercepts all events and can generate any event as 189 * A stream pipe that intercepts all events and can generate any event as
188 * output. 190 * output.
189 * 191 *
190 * Each incoming event on this [StreamSink] is passed to the corresponding 192 * Each incoming event on this [StreamSink] is passed to the corresponding
191 * provided event handler, along with a [StreamSink] linked to the [output] of 193 * provided event handler, along with a [StreamSink] linked to the [output] of
192 * this pipe. 194 * this pipe.
193 * The handler can then decide which events to send to the output 195 * The handler can then decide which events to send to the output
194 */ 196 */
195 class PipeStream<S, T> extends _ForwardingStream<S, T> { 197 class PipeStream<S, T> extends _ForwardingTransformer<S, T> {
196 final _TransformDataHandler<S, T> _onData; 198 final _TransformDataHandler<S, T> _onData;
197 final _TransformErrorHandler<T> _onError; 199 final _TransformErrorHandler<T> _onError;
198 final _TransformDoneHandler<T> _onDone; 200 final _TransformDoneHandler<T> _onDone;
199 StreamSink<T> _sink; 201 StreamSink<T> _sink;
200 202
201 PipeStream({void onData(S data, StreamSink<T> sink), 203 PipeStream({void onData(S data, StreamSink<T> sink),
202 void onError(AsyncError data, StreamSink<T> sink), 204 void onError(AsyncError data, StreamSink<T> sink),
203 void onDone(StreamSink<T> sink)}) 205 void onDone(StreamSink<T> sink)})
204 : this._onData = (onData == null ? _defaultHandleData : onData), 206 : this._onData = (onData == null ? _defaultHandleData : onData),
205 this._onError = (onError == null ? _defaultHandleError : onError), 207 this._onError = (onError == null ? _defaultHandleError : onError),
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 259
258 /** 260 /**
259 * A stream pipe that intercepts all events and can generate any event as 261 * A stream pipe that intercepts all events and can generate any event as
260 * output. 262 * output.
261 * 263 *
262 * Each incoming event on this [StreamSink] is passed to the corresponding 264 * Each incoming event on this [StreamSink] is passed to the corresponding
263 * method on [transform], along with a [StreamSink] linked to the [output] of 265 * method on [transform], along with a [StreamSink] linked to the [output] of
264 * this pipe. 266 * this pipe.
265 * The handler can then decide which events to send to the output 267 * The handler can then decide which events to send to the output
266 */ 268 */
267 class TransformStream<S, T> extends _ForwardingStream<S, T> { 269 class TransformStream<S, T> extends _ForwardingTransformer<S, T> {
268 final StreamTransformer<S, T> _transform; 270 final StreamTransformer<S, T> _transform;
269 StreamSink<T> _sink; 271 StreamSink<T> _sink;
270 272
271 TransformStream(StreamTransformer<S, T> transform) 273 TransformStream(StreamTransformer<S, T> transform)
272 : this._transform = transform { 274 : this._transform = transform {
273 // Cache the sink wrapper to avoid creating a new one for each event. 275 // Cache the sink wrapper to avoid creating a new one for each event.
274 this._sink = new _StreamImplSink(this); 276 this._sink = new _StreamImplSink(this);
275 } 277 }
276 278
277 void _handleData(S data) { 279 void _handleData(S data) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 void handleError(AsyncError error, StreamSink<T> sink) { 325 void handleError(AsyncError error, StreamSink<T> sink) {
324 _handleError(error, sink); 326 _handleError(error, sink);
325 } 327 }
326 328
327 void handleDone(StreamSink<T> sink) { 329 void handleDone(StreamSink<T> sink) {
328 _handleDone(sink); 330 _handleDone(sink);
329 } 331 }
330 } 332 }
331 333
332 334
333 class TakeStream<T> extends _ForwardingStream<T, T> { 335 class TakeStream<T> extends _ForwardingTransformer<T, T> {
334 int _remaining; 336 int _remaining;
335 337
336 TakeStream(int count) 338 TakeStream(int count)
337 : this._remaining = count { 339 : this._remaining = count {
338 if (count is! int) throw new ArgumentError(count); 340 if (count is! int) throw new ArgumentError(count);
339 } 341 }
340 342
341 void _handleData(T inputEvent) { 343 void _handleData(T inputEvent) {
342 if (_remaining > 0) { 344 if (_remaining > 0) {
343 _add(inputEvent); 345 _add(inputEvent);
344 _remaining -= 1; 346 _remaining -= 1;
345 if (_remaining == 0) { 347 if (_remaining == 0) {
346 // Closing also unsubscribes all subscribers, which unsubscribes 348 // Closing also unsubscribes all subscribers, which unsubscribes
347 // this from source. 349 // this from source.
348 _close(); 350 _close();
349 } 351 }
350 } 352 }
351 } 353 }
352 } 354 }
353 355
354 356
355 class TakeWhileStream<T> extends _ForwardingStream<T, T> { 357 class TakeWhileStream<T> extends _ForwardingTransformer<T, T> {
356 final _Predicate<T> _test; 358 final _Predicate<T> _test;
357 359
358 TakeWhileStream(bool test(T value)) 360 TakeWhileStream(bool test(T value))
359 : this._test = test; 361 : this._test = test;
360 362
361 void _handleData(T inputEvent) { 363 void _handleData(T inputEvent) {
362 bool satisfies; 364 bool satisfies;
363 try { 365 try {
364 satisfies = _test(inputEvent); 366 satisfies = _test(inputEvent);
365 } catch (e, s) { 367 } catch (e, s) {
366 _signalError(new AsyncError(e, s)); 368 _signalError(new AsyncError(e, s));
367 // The test didn't say true. Didn't say false either, but we stop anyway. 369 // The test didn't say true. Didn't say false either, but we stop anyway.
368 _close(); 370 _close();
369 return; 371 return;
370 } 372 }
371 if (satisfies) { 373 if (satisfies) {
372 _add(inputEvent); 374 _add(inputEvent);
373 } else { 375 } else {
374 _close(); 376 _close();
375 } 377 }
376 } 378 }
377 } 379 }
378 380
379 class SkipStream<T> extends _ForwardingStream<T, T> { 381 class SkipStream<T> extends _ForwardingTransformer<T, T> {
380 int _remaining; 382 int _remaining;
381 383
382 SkipStream(int count) 384 SkipStream(int count)
383 : this._remaining = count{ 385 : this._remaining = count{
384 if (count is! int) throw new ArgumentError(count); 386 if (count is! int) throw new ArgumentError(count);
385 } 387 }
386 388
387 void _handleData(T inputEvent) { 389 void _handleData(T inputEvent) {
388 if (_remaining > 0) { 390 if (_remaining > 0) {
389 _remaining--; 391 _remaining--;
390 return; 392 return;
391 } 393 }
392 return _add(inputEvent); 394 return _add(inputEvent);
393 } 395 }
394 } 396 }
395 397
396 class SkipWhileStream<T> extends _ForwardingStream<T, T> { 398 class SkipWhileStream<T> extends _ForwardingTransformer<T, T> {
397 final _Predicate<T> _test; 399 final _Predicate<T> _test;
398 bool _hasFailed = false; 400 bool _hasFailed = false;
399 401
400 SkipWhileStream(bool test(T value)) 402 SkipWhileStream(bool test(T value))
401 : this._test = test; 403 : this._test = test;
402 404
403 void _handleData(T inputEvent) { 405 void _handleData(T inputEvent) {
404 if (_hasFailed) { 406 if (_hasFailed) {
405 _add(inputEvent); 407 _add(inputEvent);
406 } 408 }
407 bool satisfies; 409 bool satisfies;
408 try { 410 try {
409 satisfies = _test(inputEvent); 411 satisfies = _test(inputEvent);
410 } catch (e, s) { 412 } catch (e, s) {
411 _signalError(new AsyncError(e, s)); 413 _signalError(new AsyncError(e, s));
412 // A failure to return a boolean is considered "not matching". 414 // A failure to return a boolean is considered "not matching".
413 _hasFailed = true; 415 _hasFailed = true;
414 return; 416 return;
415 } 417 }
416 if (!satisfies) { 418 if (!satisfies) {
417 _hasFailed = true; 419 _hasFailed = true;
418 _add(inputEvent); 420 _add(inputEvent);
419 } 421 }
420 } 422 }
421 } 423 }
422 424
423 typedef bool _Equality<T>(T a, T b); 425 typedef bool _Equality<T>(T a, T b);
424 426
425 class DistinctStream<T> extends _ForwardingStream<T, T> { 427 class DistinctStream<T> extends _ForwardingTransformer<T, T> {
426 static var _SENTINEL = new Object(); 428 static var _SENTINEL = new Object();
427 429
428 _Equality<T> _equals; 430 _Equality<T> _equals;
429 var _previous = _SENTINEL; 431 var _previous = _SENTINEL;
430 432
431 DistinctStream(bool equals(T a, T b)) 433 DistinctStream(bool equals(T a, T b))
432 : _equals = equals; 434 : _equals = equals;
433 435
434 void _handleData(T inputEvent) { 436 void _handleData(T inputEvent) {
435 if (identical(_previous, _SENTINEL)) { 437 if (identical(_previous, _SENTINEL)) {
(...skipping 11 matching lines...) Expand all
447 _signalError(new AsyncError(e, s)); 449 _signalError(new AsyncError(e, s));
448 return null; 450 return null;
449 } 451 }
450 if (!isEqual) { 452 if (!isEqual) {
451 _add(inputEvent); 453 _add(inputEvent);
452 _previous = inputEvent; 454 _previous = inputEvent;
453 } 455 }
454 } 456 }
455 } 457 }
456 } 458 }
OLDNEW
« no previous file with comments | « sdk/lib/async/stream_impl.dart ('k') | tests/lib/async/stream_single_to_multi_subscriber_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698