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

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

Issue 249183005: Move common streams in barback to their own class. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 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/barback/lib/src/node_streams.dart ('k') | pkg/barback/lib/src/phase_input.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 library barback.phase; 5 library barback.phase;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'asset_cascade.dart'; 9 import 'asset_cascade.dart';
10 import 'asset_id.dart'; 10 import 'asset_id.dart';
11 import 'asset_node.dart'; 11 import 'asset_node.dart';
12 import 'errors.dart'; 12 import 'errors.dart';
13 import 'group_runner.dart'; 13 import 'group_runner.dart';
14 import 'log.dart'; 14 import 'log.dart';
15 import 'multiset.dart'; 15 import 'multiset.dart';
16 import 'node_streams.dart';
16 import 'phase_forwarder.dart'; 17 import 'phase_forwarder.dart';
17 import 'phase_input.dart'; 18 import 'phase_input.dart';
18 import 'phase_output.dart'; 19 import 'phase_output.dart';
19 import 'stream_pool.dart';
20 import 'transformer.dart'; 20 import 'transformer.dart';
21 import 'transformer_group.dart'; 21 import 'transformer_group.dart';
22 import 'utils.dart'; 22 import 'utils.dart';
23 23
24 /// One phase in the ordered series of transformations in an [AssetCascade]. 24 /// One phase in the ordered series of transformations in an [AssetCascade].
25 /// 25 ///
26 /// Each phase can access outputs from previous phases and can in turn pass 26 /// Each phase can access outputs from previous phases and can in turn pass
27 /// outputs to later phases. Phases are processed strictly serially. All 27 /// outputs to later phases. Phases are processed strictly serially. All
28 /// transforms in a phase will be complete before moving on to the next phase. 28 /// transforms in a phase will be complete before moving on to the next phase.
29 /// Within a single phase, all transforms will be run in parallel. 29 /// Within a single phase, all transforms will be run in parallel.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 /// that input isn't consumed by any transformers, it will be forwarded 71 /// that input isn't consumed by any transformers, it will be forwarded
72 /// through the PhaseInput. However, it's possible that it was consumed by a 72 /// through the PhaseInput. However, it's possible that it was consumed by a
73 /// group, and so shouldn't be forwarded through the phase as a whole. 73 /// group, and so shouldn't be forwarded through the phase as a whole.
74 /// 74 ///
75 /// In order to detect whether an output has been forwarded through a group or 75 /// In order to detect whether an output has been forwarded through a group or
76 /// a PhaseInput, we must be able to distinguish it from other outputs with 76 /// a PhaseInput, we must be able to distinguish it from other outputs with
77 /// the same id. To do so, we check if its origin is in [_inputOrigins]. If 77 /// the same id. To do so, we check if its origin is in [_inputOrigins]. If
78 /// so, it's been forwarded unmodified. 78 /// so, it's been forwarded unmodified.
79 final _inputOrigins = new Multiset<AssetNode>(); 79 final _inputOrigins = new Multiset<AssetNode>();
80 80
81 /// A stream that emits an event whenever [this] is no longer dirty. 81 /// The streams exposed by this phase.
82 /// 82 final _streams = new NodeStreams();
83 /// This is synchronous in order to guarantee that it will emit an event as 83 Stream get onDone => _streams.onDone;
84 /// soon as [isDirty] flips from `true` to `false`. 84 Stream<AssetNode> get onAsset => _streams.onAsset;
85 Stream get onDone => _onDoneController.stream; 85 Stream<LogEntry> get onLog => _streams.onLog;
86 final _onDoneController = new StreamController.broadcast(sync: true);
87
88 /// A stream that emits any new assets emitted by [this].
89 ///
90 /// Assets are emitted synchronously to ensure that any changes are thoroughly
91 /// propagated as soon as they occur. Only a phase with no [next] phase will
92 /// emit assets.
93 Stream<AssetNode> get onAsset => _onAssetController.stream;
94 final _onAssetController =
95 new StreamController<AssetNode>.broadcast(sync: true);
96 86
97 /// Whether [this] is dirty and still has more processing to do. 87 /// Whether [this] is dirty and still has more processing to do.
98 /// 88 ///
99 /// A phase is considered dirty if any of the previous phases in the same 89 /// A phase is considered dirty if any of the previous phases in the same
100 /// cascade are dirty, since those phases could emit an asset that this phase 90 /// cascade are dirty, since those phases could emit an asset that this phase
101 /// will then need to process. 91 /// will then need to process.
102 bool get isDirty => (previous != null && previous.isDirty) || 92 bool get isDirty => (previous != null && previous.isDirty) ||
103 _inputs.values.any((input) => input.isDirty) || 93 _inputs.values.any((input) => input.isDirty) ||
104 _groups.values.any((group) => group.isDirty); 94 _groups.values.any((group) => group.isDirty);
105 95
106 /// A stream that emits an event whenever any transforms in this phase logs
107 /// an entry.
108 Stream<LogEntry> get onLog => _onLogPool.stream;
109 final _onLogPool = new StreamPool<LogEntry>.broadcast();
110
111 /// The previous phase in the cascade, or null if this is the first phase. 96 /// The previous phase in the cascade, or null if this is the first phase.
112 final Phase previous; 97 final Phase previous;
113 98
114 /// The subscription to [previous]'s [onDone] stream. 99 /// The subscription to [previous]'s [onDone] stream.
115 StreamSubscription _previousOnDoneSubscription; 100 StreamSubscription _previousOnDoneSubscription;
116 101
117 /// The subscription to [previous]'s [onAsset] stream. 102 /// The subscription to [previous]'s [onAsset] stream.
118 StreamSubscription<AssetNode> _previousOnAssetSubscription; 103 StreamSubscription<AssetNode> _previousOnAssetSubscription;
119 104
120 /// A map of asset ids to completers for [getInput] requests. 105 /// A map of asset ids to completers for [getInput] requests.
(...skipping 14 matching lines...) Expand all
135 // TODO(nweiz): Rather than passing the cascade and the phase everywhere, 120 // TODO(nweiz): Rather than passing the cascade and the phase everywhere,
136 // create an interface that just exposes [getInput]. Emit errors via 121 // create an interface that just exposes [getInput]. Emit errors via
137 // [AssetNode]s. 122 // [AssetNode]s.
138 Phase(AssetCascade cascade, String location) 123 Phase(AssetCascade cascade, String location)
139 : this._(cascade, location, 0); 124 : this._(cascade, location, 0);
140 125
141 Phase._(this.cascade, this._location, this._index, [this.previous]) { 126 Phase._(this.cascade, this._location, this._index, [this.previous]) {
142 if (previous != null) { 127 if (previous != null) {
143 _previousOnAssetSubscription = previous.onAsset.listen(addInput); 128 _previousOnAssetSubscription = previous.onAsset.listen(addInput);
144 _previousOnDoneSubscription = previous.onDone.listen((_) { 129 _previousOnDoneSubscription = previous.onDone.listen((_) {
145 if (!isDirty) _onDoneController.add(null); 130 if (!isDirty) _streams.onDoneController.add(null);
146 }); 131 });
147 } 132 }
148 133
149 onDone.listen((_) { 134 onDone.listen((_) {
150 // All the previous phases have finished building. If anyone's still 135 // All the previous phases have finished building. If anyone's still
151 // waiting for outputs, cut off the wait; we won't be generating them, 136 // waiting for outputs, cut off the wait; we won't be generating them,
152 // at least until a source asset changes. 137 // at least until a source asset changes.
153 for (var completer in _pendingOutputRequests.values) { 138 for (var completer in _pendingOutputRequests.values) {
154 completer.complete(null); 139 completer.complete(null);
155 } 140 }
(...skipping 24 matching lines...) Expand all
180 _handleOutputWithoutForwarder(forwarder.output); 165 _handleOutputWithoutForwarder(forwarder.output);
181 } 166 }
182 167
183 _inputOrigins.add(node.origin); 168 _inputOrigins.add(node.origin);
184 var input = new PhaseInput(this, node, "$_location.$_index"); 169 var input = new PhaseInput(this, node, "$_location.$_index");
185 _inputs[node.id] = input; 170 _inputs[node.id] = input;
186 input.input.whenRemoved(() { 171 input.input.whenRemoved(() {
187 _inputOrigins.remove(node.origin); 172 _inputOrigins.remove(node.origin);
188 _inputs.remove(node.id); 173 _inputs.remove(node.id);
189 _forwarders.remove(node.id).remove(); 174 _forwarders.remove(node.id).remove();
190 if (!isDirty) _onDoneController.add(null); 175 if (!isDirty) _streams.onDoneController.add(null);
191 }); 176 });
192 input.onAsset.listen(_handleOutput); 177 input.onAsset.listen(_handleOutput);
193 _onLogPool.add(input.onLog); 178 _streams.onLogPool.add(input.onLog);
194 input.onDone.listen((_) { 179 input.onDone.listen((_) {
195 if (!isDirty) _onDoneController.add(null); 180 if (!isDirty) _streams.onDoneController.add(null);
196 }); 181 });
197 182
198 input.updateTransformers(_transformers); 183 input.updateTransformers(_transformers);
199 184
200 for (var group in _groups.values) { 185 for (var group in _groups.values) {
201 group.addInput(node); 186 group.addInput(node);
202 } 187 }
203 } 188 }
204 189
205 // TODO(nweiz): If the output is available when this is called, it's 190 // TODO(nweiz): If the output is available when this is called, it's
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 .toSet(); 244 .toSet();
260 var oldGroups = _groups.keys.toSet(); 245 var oldGroups = _groups.keys.toSet();
261 for (var removed in oldGroups.difference(newGroups)) { 246 for (var removed in oldGroups.difference(newGroups)) {
262 _groups.remove(removed).remove(); 247 _groups.remove(removed).remove();
263 } 248 }
264 249
265 for (var added in newGroups.difference(oldGroups)) { 250 for (var added in newGroups.difference(oldGroups)) {
266 var runner = new GroupRunner(cascade, added, "$_location.$_index"); 251 var runner = new GroupRunner(cascade, added, "$_location.$_index");
267 _groups[added] = runner; 252 _groups[added] = runner;
268 runner.onAsset.listen(_handleOutput); 253 runner.onAsset.listen(_handleOutput);
269 _onLogPool.add(runner.onLog); 254 _streams.onLogPool.add(runner.onLog);
270 runner.onDone.listen((_) { 255 runner.onDone.listen((_) {
271 if (!isDirty) _onDoneController.add(null); 256 if (!isDirty) _streams.onDoneController.add(null);
272 }); 257 });
273 for (var input in _inputs.values) { 258 for (var input in _inputs.values) {
274 runner.addInput(input.input); 259 runner.addInput(input.input);
275 } 260 }
276 } 261 }
277 262
278 for (var forwarder in _forwarders.values) { 263 for (var forwarder in _forwarders.values) {
279 forwarder.updateTransformers(_transformers.length, _groups.length); 264 forwarder.updateTransformers(_transformers.length, _groups.length);
280 } 265 }
281 } 266 }
(...skipping 27 matching lines...) Expand all
309 /// Mark this phase as removed. 294 /// Mark this phase as removed.
310 /// 295 ///
311 /// This will remove all the phase's outputs. 296 /// This will remove all the phase's outputs.
312 void remove() { 297 void remove() {
313 for (var input in _inputs.values.toList()) { 298 for (var input in _inputs.values.toList()) {
314 input.remove(); 299 input.remove();
315 } 300 }
316 for (var group in _groups.values) { 301 for (var group in _groups.values) {
317 group.remove(); 302 group.remove();
318 } 303 }
319 _onAssetController.close(); 304 _streams.close();
320 _onLogPool.close();
321 if (_previousOnDoneSubscription != null) { 305 if (_previousOnDoneSubscription != null) {
322 _previousOnDoneSubscription.cancel(); 306 _previousOnDoneSubscription.cancel();
323 } 307 }
324 if (_previousOnAssetSubscription != null) { 308 if (_previousOnAssetSubscription != null) {
325 _previousOnAssetSubscription.cancel(); 309 _previousOnAssetSubscription.cancel();
326 } 310 }
327 } 311 }
328 312
329 /// Add [asset] as an output of this phase. 313 /// Add [asset] as an output of this phase.
330 void _handleOutput(AssetNode asset) { 314 void _handleOutput(AssetNode asset) {
(...skipping 18 matching lines...) Expand all
349 333
350 var exception = _outputs[asset.id].collisionException; 334 var exception = _outputs[asset.id].collisionException;
351 if (exception != null) cascade.reportError(exception); 335 if (exception != null) cascade.reportError(exception);
352 } 336 }
353 337
354 /// Emit [asset] as an output of this phase. 338 /// Emit [asset] as an output of this phase.
355 /// 339 ///
356 /// This should be called after [_handleOutput], so that collisions are 340 /// This should be called after [_handleOutput], so that collisions are
357 /// resolved. 341 /// resolved.
358 void _emit(AssetNode asset) { 342 void _emit(AssetNode asset) {
359 _onAssetController.add(asset); 343 _streams.onAssetController.add(asset);
360 _providePendingAsset(asset); 344 _providePendingAsset(asset);
361 } 345 }
362 346
363 /// Provide an asset to a pending [getOutput] call. 347 /// Provide an asset to a pending [getOutput] call.
364 void _providePendingAsset(AssetNode asset) { 348 void _providePendingAsset(AssetNode asset) {
365 // If anyone's waiting for this asset, provide it to them. 349 // If anyone's waiting for this asset, provide it to them.
366 var request = _pendingOutputRequests.remove(asset.id); 350 var request = _pendingOutputRequests.remove(asset.id);
367 if (request == null) return; 351 if (request == null) return;
368 352
369 if (asset.state.isAvailable) { 353 if (asset.state.isAvailable) {
370 request.complete(asset); 354 request.complete(asset);
371 return; 355 return;
372 } 356 }
373 357
374 // A lazy asset may be emitted while still dirty. If so, we wait until it's 358 // A lazy asset may be emitted while still dirty. If so, we wait until it's
375 // either available or removed before trying again to access it. 359 // either available or removed before trying again to access it.
376 assert(asset.state.isDirty); 360 assert(asset.state.isDirty);
377 asset.force(); 361 asset.force();
378 asset.whenStateChanges().then((state) { 362 asset.whenStateChanges().then((state) {
379 if (state.isRemoved) return getOutput(asset.id); 363 if (state.isRemoved) return getOutput(asset.id);
380 return asset; 364 return asset;
381 }).then(request.complete).catchError(request.completeError); 365 }).then(request.complete).catchError(request.completeError);
382 } 366 }
383 367
384 String toString() => "phase $_location.$_index"; 368 String toString() => "phase $_location.$_index";
385 } 369 }
OLDNEW
« no previous file with comments | « pkg/barback/lib/src/node_streams.dart ('k') | pkg/barback/lib/src/phase_input.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698