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

Side by Side Diff: pkg/barback/lib/src/stream_replayer.dart

Issue 43143002: Avoid sending needless data between isolates in "pub serve" and "pub build" (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Merge with bleeding edge Created 7 years, 1 month 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) 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 library barback.stream_replayer; 5 library barback.stream_replayer;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection'; 8 import 'dart:collection';
9 9
10 import 'utils.dart'; 10 import 'utils.dart';
11 11
12 /// Records the values and errors that are sent through a stream and allows them 12 /// Records the values and errors that are sent through a stream and allows them
13 /// to be replayed arbitrarily many times. 13 /// to be replayed arbitrarily many times.
14 ///
15 /// This only listens to the wrapped stream when a replayed stream gets a
16 /// listener.
14 class StreamReplayer<T> { 17 class StreamReplayer<T> {
15 /// The wrapped stream. 18 /// The wrapped stream.
16 final Stream<T> _stream; 19 final Stream<T> _stream;
17 20
21 /// Whether or not [this] has started listening to [_stream].
22 bool _isSubscribed = false;
23
18 /// Whether or not [_stream] has been closed. 24 /// Whether or not [_stream] has been closed.
19 bool _isClosed = false; 25 bool _isClosed = false;
20 26
21 /// The buffer of events or errors that have already been emitted by 27 /// The buffer of events or errors that have already been emitted by
22 /// [_stream]. 28 /// [_stream].
23 /// 29 ///
24 /// Each element is a [Either] that's either a value or an error sent through 30 /// Each element is a [Either] that's either a value or an error sent through
25 /// the stream. 31 /// the stream.
26 final _buffer = new Queue<Either<T, Pair<dynamic, StackTrace>>>(); 32 final _buffer = new Queue<Either<T, Pair<dynamic, StackTrace>>>();
27 33
28 /// The controllers that are listening for future events from [_stream]. 34 /// The controllers that are listening for future events from [_stream].
29 final _controllers = new Set<StreamController<T>>(); 35 final _controllers = new Set<StreamController<T>>();
30 36
31 StreamReplayer(this._stream) { 37 StreamReplayer(this._stream);
38
39 /// Returns a stream that replays the values and errors of the input stream.
40 ///
41 /// This stream is a buffered stream.
42 Stream<T> getReplay() {
43 var controller = new StreamController<T>(onListen: _subscribe);
44
45 for (var eventOrError in _buffer) {
46 eventOrError.match(controller.add, (pair) {
47 controller.addError(pair.first, pair.second);
48 });
49 }
50 if (_isClosed) {
51 controller.close();
52 } else {
53 _controllers.add(controller);
54 }
55 return controller.stream;
56 }
57
58 /// Subscribe to [_stream] if we haven't yet done so.
59 void _subscribe() {
60 if (_isSubscribed || _isClosed) return;
61 _isSubscribed = true;
62
32 _stream.listen((data) { 63 _stream.listen((data) {
33 _buffer.add(new Either<T, dynamic>.withFirst(data)); 64 _buffer.add(new Either<T, dynamic>.withFirst(data));
34 for (var controller in _controllers) { 65 for (var controller in _controllers) {
35 controller.add(data); 66 controller.add(data);
36 } 67 }
37 }, onError: (error, [stackTrace]) { 68 }, onError: (error, [stackTrace]) {
38 _buffer.add(new Either<T, Pair<dynamic, StackTrace>>.withSecond( 69 _buffer.add(new Either<T, Pair<dynamic, StackTrace>>.withSecond(
39 new Pair<dynamic, StackTrace>(error, stackTrace))); 70 new Pair<dynamic, StackTrace>(error, stackTrace)));
40 for (var controller in _controllers) { 71 for (var controller in _controllers) {
41 controller.addError(error, stackTrace); 72 controller.addError(error, stackTrace);
42 } 73 }
43 }, onDone: () { 74 }, onDone: () {
44 _isClosed = true; 75 _isClosed = true;
45 for (var controller in _controllers) { 76 for (var controller in _controllers) {
46 controller.close(); 77 controller.close();
47 } 78 }
48 _controllers.clear(); 79 _controllers.clear();
49 }); 80 });
50 } 81 }
51
52 /// Returns a stream that replays the values and errors of the input stream.
53 ///
54 /// This stream is a buffered stream regardless of whether the input stream
55 /// was broadcast or buffered.
56 Stream<T> getReplay() {
57 var controller = new StreamController<T>();
58 for (var eventOrError in _buffer) {
59 eventOrError.match(controller.add, (pair) {
60 controller.addError(pair.first, pair.second);
61 });
62 }
63 if (_isClosed) {
64 controller.close();
65 } else {
66 _controllers.add(controller);
67 }
68 return controller.stream;
69 }
70 } 82 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698