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

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